1

我想知道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,我需要做的就是让程序集中的一个类实现某种可注入接口,在应用程序配置中添加一行并免费获得大量东西。

4

2 回答 2

6

查看.NET 4.0 中包含的托管可扩展性框架 (MEF) 。MEF 可以从外部 DLL 动态加载和注入组件。

于 2011-08-03T15:19:04.990 回答
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 中提取一些问题,但它应该为您提供问题和解决方案的要点。

于 2011-08-03T15:45:45.187 回答