为 class 作为依赖项的接口的每个具体实现组成 class 的实例
Composing an instance of a class for each concrete implementation of an interface which that class has as a dependency
不确定如何为此 post 起一个合理的标题。
说我有一个 class
[Export(typeof(IMessageSender))]
public class MessageSender : IMessageSender
{
private IMessagingInterface _messagingInterface;
private IEventAggregator _eventAggregator;
[ImportingConstructor]
public MessageSender(IMessagingInterface messagingInterface, IEventAggregator eventAggregator)
{
_messagingInterface = messagingInterface;
_eventAggregator = eventAggregator;
}
public void SendMessage(string message)
{
_messagingInterface.Write(message);
}
public InterfaceStatus GetStatus()
{
return _messagingInterface.Status;
}
...
etc. Many methods in this class.
}
和我有几个不同的IMessagingInterface
,比如
[Export(typeof(IMessagingInterface))]
public SerialPortInterface : IMessagingInterface
{
..
}
[Export(typeof(IMessagingInterface))]
public UdpInterface : IMessagingInterface
{
..
}
etc
在我的应用程序中,我目前在启动应用程序时像这样实例化不同的部分:
eventAggregator = new EventAggregator();
batch.AddExportedValue<IMessageSender>("SerialPortSender", new MessageSender(new SerialPortInterface(), eventAggregator);
batch.AddExportedValue<IMessageSender>("UdpSender", new MessageSender(new UdpInterface (), eventAggregator);
...
etc for the rest
然后我可以使用合约名称指定我想在别处注入哪个。
但是,我觉得自己在引导程序中进行此组合并使用 new
创建实例是错误且不必要的,但我还没有找到不同的方法。
看看这个 post:
Getting all types that implement an interface
然后使用Activator.CreateInstance(...)
构造实例(参见:https://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx)
应该这样做:
eventAggregator = new EventAggregator();
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
foreach (var t in types)
{
var instance = (IMyInteface)Activator.CreateInstance(t);
batch.AddExportedValue<IMessageSender>(t.Name, new MessageSender(instance, eventAggregator);
}
正如 Tchi Yuan 所指出的,使用 IOC 框架也是一种选择,例如:
这些将根据您提供的配置为您处理程序集扫描和实例创建。
我过去遇到过这个问题,我所做的是将 Microsoft Unity 与 MEF 结合使用,然后简单地将您的统一容器传递给您的 MEF extension/plugin 构造函数。使用 Unity 注册和解析命名依赖项很简单。
不确定如何为此 post 起一个合理的标题。
说我有一个 class
[Export(typeof(IMessageSender))]
public class MessageSender : IMessageSender
{
private IMessagingInterface _messagingInterface;
private IEventAggregator _eventAggregator;
[ImportingConstructor]
public MessageSender(IMessagingInterface messagingInterface, IEventAggregator eventAggregator)
{
_messagingInterface = messagingInterface;
_eventAggregator = eventAggregator;
}
public void SendMessage(string message)
{
_messagingInterface.Write(message);
}
public InterfaceStatus GetStatus()
{
return _messagingInterface.Status;
}
...
etc. Many methods in this class.
}
和我有几个不同的IMessagingInterface
,比如
[Export(typeof(IMessagingInterface))]
public SerialPortInterface : IMessagingInterface
{
..
}
[Export(typeof(IMessagingInterface))]
public UdpInterface : IMessagingInterface
{
..
}
etc
在我的应用程序中,我目前在启动应用程序时像这样实例化不同的部分:
eventAggregator = new EventAggregator();
batch.AddExportedValue<IMessageSender>("SerialPortSender", new MessageSender(new SerialPortInterface(), eventAggregator);
batch.AddExportedValue<IMessageSender>("UdpSender", new MessageSender(new UdpInterface (), eventAggregator);
...
etc for the rest
然后我可以使用合约名称指定我想在别处注入哪个。
但是,我觉得自己在引导程序中进行此组合并使用 new
创建实例是错误且不必要的,但我还没有找到不同的方法。
看看这个 post: Getting all types that implement an interface
然后使用Activator.CreateInstance(...)
构造实例(参见:https://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx)
应该这样做:
eventAggregator = new EventAggregator();
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
foreach (var t in types)
{
var instance = (IMyInteface)Activator.CreateInstance(t);
batch.AddExportedValue<IMessageSender>(t.Name, new MessageSender(instance, eventAggregator);
}
正如 Tchi Yuan 所指出的,使用 IOC 框架也是一种选择,例如:
这些将根据您提供的配置为您处理程序集扫描和实例创建。
我过去遇到过这个问题,我所做的是将 Microsoft Unity 与 MEF 结合使用,然后简单地将您的统一容器传递给您的 MEF extension/plugin 构造函数。使用 Unity 注册和解析命名依赖项很简单。