Imported class exports method - how to compose this?

Oct 21, 2010 at 10:45 AM

Hi all,
this might be a stupid question, but somehow I just don't get it...

I have a form that imports "plugins" based on a specific contract (in this case a base-class which imlpements the ICanDoIt interface).

[ImportMany]
private IEnumerable<Lazy<CanDoIt>> _plugins;

In this form the CompositionContainer composes the parts based on a directory catalog and contains the correct number of parts, so far so good.
The same form also exports a method (its just a sample for me to undestand it, so there might be better options to log something *lg*):

[Export("LogIt")]
public void LogIt(string message)
{
    Console.WriteLine(String.Format("LOGIT: {0}", message));
}

Now the above mentioned imported plugins import the method (here is one of them):

[Export(typeof(CanDoIt))]
public class CanDoIt : Contracts.ICanDoIt
{


    [Import("LogIt")]
    public Action<string> LogIt { getset; } 

    public CanDoIt()
    {
    }

    public string JustDoIt()
    {
        LogIt("FUBAR");
        return String.Format("This will be done");
    }

}

So, whenever I call the JustDoIt() method of an imported plugin I expected the imported LogIt method to be called, thus writing to the console.
It doesn't happen...

Is this because of me not composing the parts in the plugin itself (like I do in the form)?
How can I do this in a proper, nice and correct way?

Any hint is kindly appreciated.

best regards
Andy

 

Developer
Oct 21, 2010 at 5:06 PM

Just looking at what you have there it appears as though this should work. Can you show how you are composing this? Also is your property LogIt null? If not what method does it call?

Oct 21, 2010 at 5:21 PM

Hi weshaggard

here is the code where I compose the parts:

private void ComposeParts()
{
    AggregateCatalog catalog = new AggregateCatalog();
    catalog.Catalogs.Add(new DirectoryCatalog(@"D:\DEPLOY"));
    catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
    _container = new CompositionContainer(catalog);
            
    try
    {
        this._container.ComposeParts(this);
    }
    catch (CompositionException compositionException)
    {
        Console.WriteLine(compositionException.ToString());
    }
}

I added the AssemblyCatalog while trying to figure out what the problem is, I assume it is not necessary.
All related classes/files are in the DEPLOY folder (no other files in this folder)

Unfortunately I couldn't understand your question regarding the property LogIt beeing null, would you mind to concretize it?
Method Exports are quite new for me, I just exported/imported contracts so far...

Thanks a lot for your feedback weshaggard,
best regards
Andy

Developer
Oct 24, 2010 at 2:54 AM

The LogIt property I'm talking about is:

    [Import("LogIt")]
    public Action<string> LogIt { get; set; } 

You said when you call your JustDoIt method and use your LogIt property it doesn't call the log function you expect it to. So if it didn't call the method you expected what method does it call or is the value null?

Oct 25, 2010 at 7:43 AM

Hi weshaggard,
I really have to apologize for my stupidity regarding this case.
I figured out that the property was set and null, depending on the inheritance-level (base classes were set, derived classes were null).

Unfortunately (that's when the stupidity comes into play) I had a typo that triggered the interface instead of the base class itself, causing the LogIt function to not be called.

Everything now works as expected.

Thanks a lot for turning me into the correct direction, it might have took another "bunch of time" before I would have tried to debug the property you pointed out.

So, thanks a agin and have a great week,

best regards
Andy