1

I am trying to get the Exported Properties in my defined classes, but I think something is missing that I don't know of. Here is my Handler class:

public class Handler
{
    public string Message { get; private set; }
    public void Create(string msg)
    {
        Message = msg;
    }
}

My HandlerUser class is:

public class HandlerUser
{
    [Export(typeof(Handler))]
    public Handler MyHandler { get; set; }
    public string Name { get; set; }

    public HandlerUser() { MyHandler = new Handler(); }
}

And in my program.cs I have:

        var catalogs = new AggregateCatalog();
        var catalog = new ApplicationCatalog();
        catalogs.Catalogs.Add(catalog);

        CompositionContainer pluginsCompositionContainer  = new CompositionContainer(catalogs);

        HandlerUser u1 = new HandlerUser();
        u1.MyHandler.Create("U1");
        HandlerUser u2 = new HandlerUser();
        u2.MyHandler.Create("U2");

        var exports = pluginsCompositionContainer.GetExports<Handler>();
        Console.Write(exports.Count());

I expect to see 2 exports, and They should have "U1","U2" as their message, But I only see one, and the message is null. I can't figure out what's missing, I simple want to have an export of Every Handler made in code, and just be able to do some logic. Any help would be great.

aminjam
  • 646
  • 9
  • 25
  • Thanks for the answer, but that solution is exactly what I am using for `Exporting` the current MEF classes. Think of the `Handle` class as an error collecting mechanism. I am creating instances of the `Handle` class in MEF exported items, so outside of getting references to the MEF exported classes, I want to have a ErrorManager that collects all of the exported Error logs. so in other words, I am exporting two different types of information in my `HandlerUser` class. one being the original export of the actual implementation, and the other instances of `Handler` class. – aminjam May 18 '13 at 21:54

2 Answers2

0

When using MEF, you cannot export properties or methods (as types) of some class, you need to export the class itself, so your code should be like this:

    [Export(typeof(Handler))]
    public class HandlerUser : Handler
    {
        public string Name { get; set; }

        public HandlerUser() : base()
        {
        }
    }

But since you are using MEF, this means that you are trying to add extensibility to you application, considering this, i would make "Handle" an Interface and not a class, so this way anyone can implement the way they want, they just need to implement the interface.

In this case, would be like:

    public interface IHandler
    {
        string Message { get; }
        public void Create(string msg);

    }

    [Export(typeof(Handler))]
    public class HandlerUser : IHandler
    {
        public string Name { get; set; }
        public string Message { get; private set;}

        public HandlerUser() 
        {
        }

        public void Create(string msg)
        {
           this.Message = msg
        }
    }

Edit:

I have updated the answer to be clear about how MEF works with exports, you can in fact export a property, but not in the context of the question. When you do this, you will be exporting by the property name "Handler" and not the typeof(Handler) like you do in Class definition. Property and method exports are a cool feature, but there are some limitations (the max number of parameters of a method export is 4!), prefer Class Exports where possible.

More information on exporting using MEF can be found here

  • 4
    You're wrong - exporting is possible for both properties and methods. – Adi Lester May 17 '13 at 22:47
  • No, exporting is not available in this context, he wants to export the class, so he can get them by type definition. Exporting does really works for properties, but you export a String and not the type, their declaration is different. But i will update the answer to make this more clear. – Gabriel Vonlanten C. Lopes May 17 '13 at 23:06
  • 4
    It is possible to export two instances of the class by having two exporting properties where the getters return the fully constructed object. Not saying that it's the way to go, but it is possible. – Adi Lester May 17 '13 at 23:11
  • Yes, it is possible, but like you said yourself, this is not the best approach. But thanks for the observation, i think know my answer is more accurate for future users that may run into some similar situations, intead of thinking that is impossible to export properties (as my earlier answer could make people think that) :) – Gabriel Vonlanten C. Lopes May 17 '13 at 23:15
0

The reason you see only one export is because the CompositionContainer doesn't know about the other two objects you created yourself.

To let the CompositionContainer use the two other Handlers, pass each HandleUser to the CompositionContainer.ComposeParts method. This one will register the handlers to the container.

pluginsCompositionContainer.ComposeParts(u1);
pluginsCompositionContainer.ComposeParts(u2);

Then when you get the exports you will notice that they are not two (as you initially expected), but three. The two that you created yourself and registered to the container using CompositionContainer.ComposeParts plus the one that the container has created automatically (actually it's a Lazy<Handler>). This last one is the one you see in your sample code. When you will try to access this specific exported value, the container will create an instance of HandlerUser and then return the reference to the Handler.

Panos Rontogiannis
  • 4,154
  • 1
  • 24
  • 29