Reputation: 349
Was unsure how to make a sensible title for this post.
Say I have a 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.
}
and I have several different IMessagingInterface
, such as
[Export(typeof(IMessagingInterface))]
public SerialPortInterface : IMessagingInterface
{
..
}
[Export(typeof(IMessagingInterface))]
public UdpInterface : IMessagingInterface
{
..
}
etc
In my application, I currently instantiate the different parts like this at the startup of my application:
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
Then I can specify which one I want injected elsewhere by using the contract name.
However, I feel like doing this composition myself in the bootstrapper and creating instances with new
is wrong and unnecessary, but I haven't found a way to do it differently.
Upvotes: 0
Views: 182
Reputation: 979
Have a look at this post: Getting all types that implement an interface
And then use Activator.CreateInstance(...)
to construct the instances (see: https://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx)
Something like this should do it:
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);
}
As Tchi Yuan pointed out, using a IOC framework is also an option such as:
These will handle the scanning of assemblies and instance creation for you according to the configurations you provide.
Upvotes: 1
Reputation: 4278
I've had this problem in the past and what I did is that I used Microsoft Unity in conjuncture with MEF and then simply pass your unity container to your MEF extension/plugin constructor. Registering and resolving named dependencies with Unity is trivial.
Upvotes: 1