C# 如何正确地将实现细节解耦到.net中的类库中
我想知道在c#(或者甚至是cli)中是否有一种标准方法可以有效地将实现逻辑解耦到单独的类库/程序集中,这些类库/程序集将由一个进程动态加载,该进程将基于公共接口在这些库上执行操作 更准确地说: 假设我正在构建一个接收消息的服务,并将这些消息的处理委托给其他人。比如: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)
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”中进行了描述