【问题标题】:how to properly decouple implementation specifics into class libraries in .net如何将实现细节正确地解耦到.net中的类库中
【发布时间】:2011-08-03 15:05:53
【问题描述】:

我想知道在 c#(甚至可能是 cli)中是否有一种标准方法可以有效地将实现逻辑解耦为单独的类库/程序集,这些类库/程序集将由一个进程动态加载,该进程将基于一个对这些库执行操作通用接口。

更准确地说: 假设我正在构建一个接收消息的服务,并将这些消息的处理委托给其他东西。比如:

while(true){
   message = read_message_from_somewhere();
   class_from_another_lib.do_somthing_with_Message(message); 
}

我希望进程在运行时从某种配置加载类库。我假设这个库会有一些主类或类工厂,它们实现了一些接口部分,如下所示:

ISomePublicIface{
   void do_somthing_with_Message(messageT);
}

这一切都感觉有点像 java beish,我需要做的就是让程序集中的一个类实现某种可注入接口,在应用程序配置中添加一行并免费获得大量东西。

【问题讨论】:

标签: c# .net design-patterns decoupling dynamic-loading


【解决方案1】:

看看Managed Extensibility Framework (MEF),它包含在 .NET 4.0 中。 MEF 可以从外部 DLL 动态加载和注入组件。

【讨论】:

  • 是我遗漏了什么还是 MEF 没有提供任何动态加载程序集的功能?这是我应该照顾自己的事情吗?
  • 使用 AssemblyCatalog 从单个程序集加载类型,或使用 DirectoryCatalog 从给定目录中找到的所有程序集加载。它们在documentation 中有描述
【解决方案2】:

如果您喜欢 NIH 解决方案...我已经编写了这个问题的稍微冗长的版本,它允许您使用 DI 容器来存储消息的处理程序并根据消息分派到相关的处理程序。我在这里对容器使用了 autofac,但是只要它可以解析开放的泛型,任何东西都应该是合适的:

// Message marker interface
interface IMessage {}

// Message handler interface
interface IHandles<T> where T: IMessage
{
    void Handle(T message);
}

// A message which defines mooing
class MooMessage : IMessage {}

// A message which defines woofing
class WoofMessage : IMessage {}

// A handler for moo messages
class MooHandler : IHandles<MooMessage>
{
    public void Handle(MooMessage message)
    {
        Console.WriteLine("moo");
    }
}

// A handler for woof messages
class WoofHandler : IHandles<WoofMessage>
{
    public void Handle(WoofMessage message)
    {
        Console.WriteLine("woof");
    }
}

class Program
{
    // Generate some test messages
    static IEnumerable<IMessage> MessageGenerator()
    {
        yield return new WoofMessage();
        yield return new MooMessage();
    }

    static void Main(string[] args)
    {
        // configure container
        var builder = new ContainerBuilder();
        // Register message handlers here through configuration or convention...
        builder.RegisterType<WoofHandler>().AsImplementedInterfaces();
        builder.RegisterType<MooHandler>().AsImplementedInterfaces();
        var container = builder.Build();

        // handle all messages until done
        foreach (var message in MessageGenerator())
        {
            // resolve the handler for the message from the container
            var handler = container
                .Resolve(typeof(IHandles<>)
                .MakeGenericType(message.GetType()));

            // call the handler - you have to do this using reflection unfortunately
            // due to the nature of open generics.
            handler
                .GetType()
                .GetMethod("Handle")
                .Invoke(handler, new object[] { message });
        }
    }
}

您显然希望从 Main 中提取一些问题,但它应该为您提供问题和解决方案的要点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-03
    • 1970-01-01
    相关资源
    最近更新 更多