简体   繁体   English

在WebApi应用程序中将MEF与DI结合使用

[英]Using MEF with DI in a WebApi application

I'm planning on using MEF to implement a plugin architecture for my import plugins. 我正计划使用MEF为我的导入插件实现插件体系结构。 These plugins will import various data into the db (eg. customers, addresses, products, etc). 这些插件会将各种数据(例如,客户,地址,产品等)导入数据库。

The import plugin class looks like this: 导入插件类如下所示:

public interface IImportPlugin
{
    string Name { get; }
    void Import();
}

[Export(typeof(IImportPlugin))]
public class ImportCustomers : IImportPlugin
{
    private readonly ICustomerService customerService;

    public string Name
    {
        get { this.GetType().Name; }
    }

    public ImportCustomers(ICustomerService _customerService) 
    {
        customerService = _customerService;
    }

    public void Import() {}
}

I then have a controller, which first gets all import plugins as follows: 然后,我有一个控制器,它首先获取所有导入插件,如下所示:

public IHttpActionResult GetImportPlugins()
{
    var catalog = new AggregateCatalog();

    catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")));

    var directoryCatalog = new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins"));
    catalog.Catalogs.Add(directoryCatalog);

    var container = new CompositionContainer(catalog);
    container.ComposeParts();

    var list = container.GetExportedValues<IImportPlugin>().Select(x => x.Name);
    return Ok(list);
}

The import plugin needs to reference my Services assembly because this is where the BL takes place. 导入插件需要引用我的Services程序集,因为这是发生BL的地方。 I register my services in the main WebApi project with Autofac as follows: 我在Autofac的主要WebApi项目中注册我的服务,如下所示:

builder.RegisterAssemblyTypes(assemblies)
  .Where(t => t.Name.EndsWith("Service"))
  .AsImplementedInterfaces()
  .InstancePerRequest();

Is it possible to pass different services to different import plugins? 是否可以将不同的服务传递给不同的导入插件?

For example, if I'm importing products I need to pass the ProductService , and if I'm importing customers I might need to pass CustomerService and AddressService . 例如,如果要导入产品,则需要传递ProductService ,如果要导入客户,则可能需要传递CustomerServiceAddressService

How can I inject these services inside the plugins (through their constructors just like one would do in a controller)? 如何将这些服务注入插件中(通过它们的构造函数,就像在控制器中那样)?

For plugin-like architecture, you need three things: 对于类似插件的体系结构,您需要三件事:

  • Contracts (basicaly assembly containing only interfaces and simple objects withouth BL). 合同(基本程序集,仅包含接口和简单对象,而没有BL)。 This will be used as API for your plugins. 这将用作您插件的API。 Also, here you can specify IImportPlugin interface. 另外,您可以在此处指定IImportPlugin接口。

  • Module which responsibily will be loading plugin modules from some folder, or from somewhere else. 负责任的模块将从某个文件夹或其他位置加载插件模块。

  • Module in each plugin you create, to register your plugin as IImportPlugin inside DI container. 您创建的每个插件中的模块,以将插件注册为DI容器中的IImportPlugin。

You can register your plugin modules like this in loop: 您可以像这样在循环中注册插件模块:

builder.RegisterAssemblyModules(/*plugin 'Assembly' goes here*/);

In your plugin assembly, in specific module, you specify only your plugin registration: 在插件程序集中的特定模块中,您仅指定插件注册:

public class MyPluginModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.Register<ImportCustomers>().As<IImportPlugin>();
    }
}

Then in plugin implementation ImportCustomer you can use everything from Contract assembly (for example your ICustomerService interface). 然后,在插件实现ImportCustomer中,您可以使用来自Contract程序集的所有内容(例如ICustomerService接口)。 And if your system registered dependecies for your plugin - it will succesfuly load into DI container. 而且,如果您的系统为插件注册了依赖项-它将成功加载到DI容器中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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