I am trying to understand MEF and did a few samples on that. But, when I try to execute this particular code below, I am with an exception.
ConsoleApplication2.program
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
namespace ConsoleApplication2
{
class Program
{
[Import(typeof(Contracts.IInput))]
public Contracts.IInput myinterface { get; set; }
public void Method()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(container );
Console.WriteLine(myinterface.IsValid());
}
public static void Main(string[] args)
{
var obj = new Program();
obj.Method();
Console.ReadLine();
}
}
}
I have a separate project for defining an interface.
namespace Contracts
{
public interface IInput
{
//All classes that inherit IInput must implement the IsValid Property.
string IsValid();
}
}
And in another separate project, I use a export class.
using System.ComponentModel.Composition;
using Contracts;
namespace Plugin
{
[Export(typeof(Contracts.IInput))]
public class Plugin : IInput
{
public string IsValid()
{
return "1";
}
}
}
Now, all these produce (two library files and an executable) at the same “bin\Debug” folder.But on executing when reaching the code, “composeParts(this)” an exception occurs like below,
Object reference not set to an instance of an object.
When I try to change “Composeparts(container)” there is another exception like below,”
**> The composition produced a single composition error. The root cause is
provided below. Review the CompositionException.Errors property for
more detailed information.1) Cannot populate the collection
‘ConsoleApplication2.Program.myinterface’ because it does not
implement ICollection or is read-only. If the collection is not
IEnumerable or T[] it must implement ICollection and be either
pre-initialized or be writable with a default constructor.Resulting in: Cannot activate part ‘ConsoleApplication2.Program’
Element: ConsoleApplication2.Program –> ConsoleApplication2.Program **
- Can you please show me where I am going wrong?
- I thought both composeparts(this) and composeparts(container) were both same since I use Assembly.GetExecutingAssembly(). If so, then why did two different exceptions get thrown?
I used importmany like
class Program
{
[ImportMany(typeof(Contracts.IInput))]
public IEnumerable<Contracts.IInput> myinterface { get; set; }
public void Method()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
try
{
container.ComposeParts(container);
foreach (var i in myinterface)
Console.WriteLine(i.IsValid());
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
But in this case, still myinterface is null and this throws a null reference exception.
There are 2 problems:
First:
Use
ImportnotImportMany.OR
Since
ImportManyexpects a collection so you should use something like this:public IEnumerable<Contracts.IInput> myinterface { get; set; }Second:
Just as you cannot use properties that have the
Importattribute on them in the Constructor (Thats what an importing constructor is for), You can’t access them in the program’s Main function.This, for instance, will work: