Custom 'ExportFactory'

前端 未结 1 610
长发绾君心
长发绾君心 2021-02-09 20:32

A desktop application using MEF imports many \'ServiceProviders\'. Each part (ServiceProvider) is a class inside a separate DLL. All DLLs are in \'Plugin\" folder w

1条回答
  •  悲&欢浪女
    2021-02-09 20:55

    When MEF sees an import of the type ExportFactory, it treats this in a special way. Instead of looking literally for an ExportFactory export, it looks instead for a IFoo export and magically generates a factory for that type.

    Your mistake is that you expect this magic to also automatically work for your own alternative to ExportFactory which you called SrviceProviderFactory. This is not true. When you import SrviceProviderFactory somewhere, MEF literally looks for an export of that type.

    The straightforward solution is to give it this export. Manually export a factory for each IServiceProvider implementation. For example, if you have a FooServiceProvider:

    public class FooServiceProvider : IServiceProvider
    {
        public FooServiceProvider(Dependency dependency)
        {
            ...
        }
    }
    

    Then you also need to have a FooServiceProviderFactory:

    [Export(typeof(IServiceProviderFactory))]
    [ExportMetaData("foo", "bar")]
    public class FooServiceProviderFactory : IServiceProviderFactory
    {
        public IServiceProvider CreateServiceProvider(Dependency d)
        {
           return new FooServiceProvider(d);
        }
    }
    

    And then your importer can select the right factory based on metadata:

    public class FactoryUser
    {
        [ImportMany]
        public Lazy>[] Factories 
        {
            get;
            set;
        }
    
        public void DoSomething()
        {
           var factory = Factories.First(x => x.Metadata["foo"] == "bar").Value;
           var serviceProvider = factory.CreateServiceProvider(someDependency);
           ...
        }
    }
    

    The annoying thing here is that for each service provider implementation, you also need to create and export a factory implementation. You can save work by creating a common factory base class (like your SrviceProviderFactory) but you still have to derive specific classes because you can't use generic type parameters in MEF exports. update: I believe .NET 4.5 now supports exporting open generic types.

    That's why I already suggested you export Func instead, but apparently you didn't like that answer.

    You could also try to replicate the ExportFactory magic. This is possible but a very advanced use case of MEF. If you want to do that I suggest you take a look at the MEF sources of ExportFactoryProvider to see how to build your own implementation with support for parameters.

    0 讨论(0)
提交回复
热议问题