Is there a good way within MEF to
limit which particular imports I allow
a newly instantiated extension to
resolve?
Load the extension code in a separate container, and make sure that the restricted parts are not available in that container. Let's simplify the situation to these classes to construct an example:
[Export]
public class MyExtension
{
[Import]
public PublicService Service { get; set; }
}
[Export]
public class PublicService
{
}
[Export]
public class InternalService
{
}
[Export]
public class Program
{
[Import]
public MyExtension Extension { get; set; }
[Import]
public PublicService Service1 { get; set; }
[Import]
public InternalService Service2 { get; set; }
}
The goal is to allow MyExtension
to import PublicService
, but not InternalService
. Internal code like Program
should be able to import anything. You can achieve that like this:
var publicCatalog = new TypeCatalog(typeof(PublicService), typeof(MyExtension));
var publicContainer = new CompositionContainer(publicCatalog);
var internalCatalog = new TypeCatalog(typeof(Program), typeof(InternalService));
var internalContainer =
new CompositionContainer(internalCatalog, publicContainer);
var program = internalContainer.GetExport<Program>();
This code will not throw a composition exception. If you now change the import on MyExtension
to the forbidden InternalService
, you will get a composition exception as desired.
A side effect of this set-up is that PublicService
cannot import any private services either, just like MyExtension
. This kind of makes sense, because otherwise nothing would stop PublicService
from exposing a private service via a property.
I have used TypeCatalog
for the example, but in practice you should probably use something like the FilteredCatalog sample.
This particular application has
extension objects that I repeatedly
instantiate. I can import multiple
types of Controllers and Machines,
which are instantiated in different
combinations for a Project. I couldn't
find a good way to do this with MEF,
so I'm doing my own type discovery and
instantiation. Is there a good way to
do this within MEF or other DI
frameworks?
You might just be after the PartCreationPolicy
attribute, which controls whether a part is shared (as in, created only once per container) or instantiated multiple times for each import. You can also specify the RequiredCreationPolicy
parameter in an import attribute.
If that doesn't solve your problem, take a look at the PartCreator sample in the MEF sources (though note that it will probably soon be renamed to ExportFactory, it already has been in the silverlight edition of MEF).