如何正确地将实现细节解耦到.net中的类库中

时间:2011-08-03 15:05:54

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

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

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

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

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

ISomePublicIface{
   void do_somthing_with_Message(messageT);
}

这一切都让我觉得有些java isish所有我需要做的就是在一个程序集中使用一个类可注入的接口在应用程序配置中添加一行并免费获得一些东西。

2 个答案:

答案 0 :(得分:6)

查看.NET 4.0中包含的Managed Extensibility Framework (MEF)。 MEF可以动态加载和注入来自外部DLL的组件。

答案 1 :(得分:1)

如果您喜欢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中略微提出一些问题,但它应该为你提供问题和解决方案的要点。