Reputation: 2834
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.
Upvotes: 0
Views: 770
Reputation: 5022
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.
Upvotes: 1