I am studying MEF 2. Below code throws below exception:
An unhandled exception of type 'System.Composition.Hosting.CompositionFailedException' occurred in System.Composition.TypedParts.dll
Additional information: Missing dependency 'MessageSenders' on 'MEFStudy.Program'.
when calling the SatisfyImports() method. Why?
using System;
using System.Collections.Generic;
using System.Composition;
using System.Composition.Hosting;
using System.Reflection;
namespace MEFStudy
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
[ImportMany]
private List<IMessageSender> MessageSenders { get; set; }
public void Run()
{
Compose();
foreach (IMessageSender sender in MessageSenders)
{
sender.Send();
}
}
private void Compose()
{
CompositionHost host = new ContainerConfiguration().WithAssembly(Assembly.GetExecutingAssembly()).CreateContainer();
host.SatisfyImports(this); // <=========== HERE
host.Dispose();
}
}
public interface IMessageSender
{
void Send();
}
[Export(typeof(IMessageSender))]
public class EmailSender1 : IMessageSender
{
public void Send()
{
Console.WriteLine("EmailSender1");
}
}
[Export(typeof(IMessageSender))]
public class EmailSender2 : IMessageSender
{
public void Send()
{
Console.WriteLine("EmailSender2");
}
}
}
According to here, there are 2 versions of MEF.
The List<IMessageSender>
approach works with non-portable one. But not with the portable one. Is this a bug?
I accidentally changed the following code:
[ImportMany]
private List<IMessageSender> MessageSenders { get; set; }
to
[ImportMany]
private IEnumerable<IMessageSender> MessageSenders { get; set; }
And it solves the problem.
But still, why? Isn't List<T>
an IEnumerable<T>
?
And even stranger, I changed the IEnumerable to IList, it works. Why?
(I'd like to share my explanations to this.)
The following interface can reproduce exactly the same error.
interface IMyList<T> : IList<T>
{
}
[System.Composition.ImportMany] // MEF 2
private IMyList<IMessageSender> MessageSenders { get; set; }
The following MEF 2 source shows the reason.
The Equals() method of 3 SupportedContactTypes returns false with IMyList<>. So in MEF2 will not return valid export for IMyList<>. And MEF 2 allows no default value for property decorated with [ImportMany] attribute. So in the following logic, the dependency missing exception will be thrown.
So we can say, ImportMany attribute only support array and the 3 supported generic types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With