使用MEF和依赖注入

时间:2016-11-01 22:43:13

标签: c# mef

我有一个使用依赖注入记录器类型实例化的类,如下所示:

var _logger = Logger.GetLogger(LoggerType.MongoLogger);         
var service = new MyService(_logger);

在我的单元测试中,我更换了使用的记录器:

var _logger = Logger.GetLogger(LoggerType.TextFileLogger);         

现在,我想使用MEF加载MyService作为插件我创建了这样的服务:

[Export(typeof(IService))]
    public class MyService: IService
    {
        private ILogger _logger;    

        public MyService(ILogger  logger)
        {
            this._logger = logger;
        }
        public void DoServiceWork()
        {
            _logger.Log("Starting service work");
        }
    }

如何在MEF框架中使用此功能?

1 个答案:

答案 0 :(得分:2)

编辑: 使用控制台应用程序添加了更详细的示例。

Bootstrap Class

此类创建MEF容器以及初始化聚合目录。您还应该实例化其他可导出项目,例如ILogger,由程序中的其他依赖类使用。创建属性并使用Export标记它们允许在整个程序中使用这些实例。

您应该只实例化一次此类。在这个例子中,我们在启动时在主程序块中实例化它。

我们已将ContainerILogger标记为导出,因为我们希望这些实例可供其他相关类使用。

导出IService

使用Export(IService)标记MySerivce类允许它在MEF中导出。我们通过调用Container.GetExportedValue<IService>();使用MEF来获取它的实例。注意:默认情况下,MEF将使用单例共享实例,即对象将被创建一次。如果您需要非共享实例,则必须使用PartCreationPolicy(CreationPolicy.NonShared)

标记类
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition;

class Program
{
    static void Main(string[] args)
    {
        var bootstrap = new Bootstrap();
        var service = bootstrap.Container.GetExportedValue<IService>();
        service.DoServiceWork();
    }


}

public class Bootstrap
{
    [Export]
    public CompositionContainer Container { get; private set; }

    [Export(typeof(ILogger))]
    public ILogger Logger { get; private set; }

    public  Bootstrap()
    {
        //Create an aggregate catalog that will hold assembly references
        var catalog = new AggregateCatalog();

        //Adds this assembly. 
        //Exports defined in the classes and types within this assembly will now be composable
        //Add to the catalogs if there are more assemblies where exports are defined.
        catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));

        //Create the CompositionContainer with the parts in the catalog
        this.Container = new CompositionContainer(catalog);

        this.Logger = Logger.GetLogger(LoggerType.MongoLogger);
        this.Container.ComposeParts(this);
    }
}

[Export(typeof(IService))]
public class MyService : IService
{

    //adding pragma directive removes compiler warning of unassigned property/field
    //as these will be assigned by MEF import 
#pragma warning disable

    [Import]
    private ILogger _logger;

#pragma warning restore


    public MyService()
    {
        //logger will be instantiated by MEF
    }

    public void DoServiceWork()
    {
        _logger.Log("Starting service work");
    }
}