简体   繁体   中英

How do I setup mef with a class library?

I've recently started using MEF in my application, and have had no issues using it or testing classes that it acts upon inside of my main application; however, I'm just now starting to create a licensing library for my application, have run into some issues, since I'm unsure of how to set it up.

In my licensing library, I've got LicenseManager, LicenseValidator, and LicenseSigner classes:

public class LicenseManager
{
    [Import]
    private ILicenseValidator _validator;

    [Import]
    private ILicenseSigner _signer;

    public LicenseManager()
    {
        var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
        var container = new CompsitionContainer();
        container.ComposeParts();
    }
}

[Export(typeof(ILicenseSigner))]
public class LicenseSigner : ILicenseSigner
{
    ...
}

[Export(typeof(ILicenseValidator))]
public class LicenseValidator : ILicenseValidator
{
    ...
}

I find that both the validater and the signer are null after accessing them.

Which I assume is due to the fact that I'm instantiating LicenseManager before the constructor for LicenseManager can create the container; however, I'm not entirely sure how to solve the problem, since LicenseManager is intended as the only entry point into the class library. I could possibly create some sort of factory to initialize the container and return a LicenseManager instance, but that would result in a less nice library API.

I'm sort of new to the whole MEF thing. Is there something I could be doing better? Is there a way for me to take care of all the MEF loading in my main application? Any solution is better than the lack of one that I have now.

The ComposeParts call needs at least one attributed object to compose. You should pass in the LicenseManager as the argument to ComposeParts . So, your full set of code would look like:

public class LicenseManager
{
    [Import]
    private ILicenseValidator _validator;

    [Import]
    private ILicenseSigner _signer;

    public LicenseManager()
    {
        var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
        var container = new CompsitionContainer(catalog);
        container.ComposeParts(this);
    }
}

[Export(typeof(ILicenseSigner))]
public class LicenseSigner : ILicenseSigner
{
    ...
}

[Export(typeof(ILicenseValidator))]
public class LicenseValidator : ILicenseValidator
{
    ...
}

In my testing, the above code worked.

Another idea would be to delegate the choosing of the catalogs to the code implementing the library. Your constructor would become:

public LicenseManager(AggregateCatalog catalog)
{
    var container = new CompsitionContainer(catalog);
    container.ComposeParts(this);
}

This allows the program implementing your licensing library to specify where the exports will come from.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM