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

C# 如何正确地将实现细节解耦到.net中的类库中,c#,.net,design-patterns,decoupling,dynamic-loading,C#,.net,Design Patterns,Decoupling,Dynamic Loading,我想知道在c#(或者甚至是cli)中是否有一种标准方法可以有效地将实现逻辑解耦到单独的类库/程序集中,这些类库/程序集将由一个进程动态加载,该进程将基于公共接口在这些库上执行操作 更准确地说: 假设我正在构建一个接收消息的服务,并将这些消息的处理委托给其他人。比如: while(true){ message = read_message_from_somewhere(); class_from_another_lib.do_somthing_with_Message(message)

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

看看.NET 4.0中包含的。MEF可以从外部DLL动态加载和注入组件。

请查看.NET 4.0中包含的。MEF可以从外部DLL动态加载和注入组件。

如果您喜欢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 });
        }
    }
}
//消息标记接口
接口IMessage{}
//消息处理程序接口
接口i句柄,其中T:IMessage
{
无效句柄(T消息);
}
//一种定义moing的消息
类消息:IMessage{}
//定义低音的消息
类WoofMessage:IMessage{}
//moo消息的处理程序
类MooHandler:IHandles
{
公共无效句柄(MooMessage)
{
控制台写入线(“moo”);
}
}
//低音信息处理程序
WoofHandler类:IHandles
{
公共无效句柄(WoofMessage消息)
{
控制台。书写线(“woof”);
}
}
班级计划
{
//生成一些测试消息
静态IEnumerable消息生成器()
{
返回新WoofMessage();
产生返回新消息();
}
静态void Main(字符串[]参数)
{
//配置容器
var builder=new ContainerBuilder();
//通过配置或约定在此处注册消息处理程序。。。
builder.RegisterType().AsImplementedInterfaces();
builder.RegisterType().AsImplementedInterfaces();
var container=builder.Build();
//处理所有消息,直到完成
foreach(MessageGenerator()中的var消息)
{
//解析来自容器的消息的处理程序
var handler=容器
.Resolve(类型)(IHandles)
.MakeGenericType(message.GetType());
//调用处理程序-不幸的是,您必须使用反射来执行此操作
//由于开放泛型的性质。
处理者
.GetType()
.GetMethod(“句柄”)
.Invoke(处理程序,新对象[]{message});
}
}
}

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

如果您喜欢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 });
        }
    }
}
//消息标记接口
接口IMessage{}
//消息处理程序接口
接口i句柄,其中T:IMessage
{
无效句柄(T消息);
}
//一种定义moing的消息
类消息:IMessage{}
//定义低音的消息
类WoofMessage:IMessage{}
//moo消息的处理程序
类MooHandler:IHandles
{
公共无效句柄(MooMessage)
{
控制台写入线(“moo”);
}
}
//低音信息处理程序
WoofHandler类:IHandles
{
公共无效句柄(WoofMessage消息)
{
控制台。书写线(“woof”);
}
}
班级计划
{
//生成一些测试消息
静态IEnumerable消息生成器()
{
返回新WoofMessage();
产生返回新消息();
}
静态void Main(字符串[]参数)
{
//配置容器
var builder=new ContainerBuilder();
//通过配置或约定在此处注册消息处理程序。。。
builder.RegisterType().AsImplementedInterfaces();
builder.RegisterType().AsImplementedInterfaces();
var container=builder.Build();
//处理所有消息,直到完成
foreach(MessageGenerator()中的var消息)
{
//解析来自容器的消息的处理程序
var handler=容器
.Resolve(类型)(IHandles)
.MakeGenericType(message.GetType());
//调用处理程序-不幸的是,您必须使用反射来执行此操作
//由于开放泛型的性质。
处理者
.GetType()
.GetMethod(“句柄”)
.Invoke(处理程序,新对象[]{message});
}
}
}

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

检查此项检查此项检查我是否遗漏了一些内容,或者MEF是否不提供任何动态加载程序集的功能?这是我自己应该注意的吗?使用AssemblyCatalog从单个程序集中加载类型,或使用DirectoryCatalog从给定目录中找到的所有程序集中加载类型。它们在“我是否缺少som”中进行了描述