领域服务的时候,用到MEF的注入有参构造函数的方法,your master was attracted,打算稍微深挖一下,这篇来对此知识点做个总结。

一、知识点回顾

MEF作为IOC的方式之一,它的主要作用是解耦,MEF加上面向接口编程,可以使得你的设计更加灵活。我们知道类的构造函数是可以重载的,我们通过构造函数可以向对象传递参数。那么如果我们的MEF也需要通过构造函数传参怎么办呢?别担心,有我们神奇的ImportingConstructor为您解决。

二、代码示例

作为分享代码,博主还是打算用前面DDD里面领域服务用到的那个Demo,现学现卖嘛,O(∩_∩)O~

1、准备代码:

作为MEF的导入导出的对象,我们先来看三个仓储接口和实现

   public interface IUserRepository:IRepository<TB_USERS>
{
IEnumerable<TB_USERS> GetUsersByRole(TB_ROLE oRole);
}
[Export(typeof(IUserRepository))]
public class UserRepository:EFBaseRepository<TB_USERS>,IUserRepository
{
public IEnumerable<TB_USERS> GetUsersByRole(TB_ROLE oRole)
{
throw new NotImplementedException();
}
}
public interface IRoleRepository:IRepository<TB_ROLE>
{ }
[Export(typeof(IRoleRepository))]
public class RoleRepository:EFBaseRepository<TB_ROLE>,IRoleRepository
{ }
public interface IUserRoleRepository : IRepository<TB_USERROLE>
{ }
[Export(typeof(IUserRoleRepository))]
public class UserRoleRepository : EFBaseRepository<TB_USERROLE>, IUserRoleRepository
{
}
2、构造函数传入单个参数 直接来看代码吧: [Export(typeof(IPowerManagerDomainService))]
public class PowerManagerDomainService:IPowerManagerDomainService
{
private IUserRepository _userRepository = null;
private IRoleRepository _roleRepository = null;
private IUserRoleRepository _userroleRepository = null;
[ImportingConstructor]
public PowerManagerDomainService(IUserRoleRepository oUserRoleRepository)
{
_userroleRepository = oUserRoleRepository;
}
}
为什么通过这里的ImportingConstructor特性就能将参数IUserRoleRepository oUserRoleRepository顺利传进来?还记得前面的准备代码吗,IUserRoleRepository的实现类UserRoleRepository上面标记过导出[Export(typeof(IUserRepository))],所以这里能将参数顺利导入进来。还是来看看调用代码: [Import]
public IPowerManagerDomainService powerDomainService { get; set; }
static void Main(string[] args)
{
var oProgram = new Program();
Regisgter.regisgter().ComposeParts(oProgram);
Console.ReadKey();
}
来调试代码看看: 3、构造函数传入多个参数 其实多个参数和上面单个参数的的也没啥太大区别 [ImportingConstructor]
public PowerManagerDomainService(IUserRepository oUserRepository, IRoleRepository oRoleRepository)
{
_userRepository = oUserRepository;
_roleRepository = oRoleRepository;
}
同样要求IUserRepository 和 IRoleRepository 类型要有对应的Export。 4、构造函数参数有多个导出 上面的例子都是默认仓储的接口类型都只有一个导出的情况,当实际项目中,业务逻辑较复杂的时候,某一个接口往往存在多个实现类的导出,这种情况下我们要怎么办呢?比如IUserRepository仓储接口有两个实现类: [Export("userRepository_A", typeof(IUserRepository))]
public class UserRepository_A:EFBaseRepository<TB_USERS>,IUserRepository
{
public IEnumerable<TB_USERS> GetUsersByRole(TB_ROLE oRole)
{
throw new NotImplementedException();
}
}
[Export("userRepository_B", typeof(IUserRepository))]
public class UserRepository_B:EFBaseRepository<TB_USERS>,IUserRepository
{
public IEnumerable<TB_USERS> GetUsersByRole(TB_ROLE oRole)
{
throw new NotImplementedException();
}
}
这种情况下,如果我们直接在构造函数里面这样写 [ImportingConstructor]
public PowerManagerDomainService(IUserRepository oUserRepository, IRoleRepository oRoleRepository)
{
_userRepository = oUserRepository;
_roleRepository = oRoleRepository;
}
肯定是会报错的。那么我们的解决方案是: [ImportingConstructor]
public PowerManagerDomainService([Import("userRepository_A", typeof(IUserRepository))]IUserRepository oUserRepository, IRoleRepository oRoleRepository)
{
_userRepository = oUserRepository;
_roleRepository = oRoleRepository;
}
5、多个构造函数的导入 了解了上面那么多,我们还想扩展一下,我们知道构造函数是可以重载的,一个类可以有多个构造函数。那么如果我们想在多个构造函数上面同时标记ImportingConstructor特性,然后根据需要调用不同的构造函数,这样真的行吗?比如我们想这样写: [Export(typeof(IPowerManagerDomainService))]
public class PowerManagerDomainService:IPowerManagerDomainService
{
private IUserRepository _userRepository = null;
private IRoleRepository _roleRepository = null;
private IUserRoleRepository _userroleRepository = null;
[ImportingConstructor]
public PowerManagerDomainService(IUserRoleRepository oUserRoleRepository)
{
_userroleRepository = oUserRoleRepository;
}
[ImportingConstructor]
public PowerManagerDomainService([Import(typeof(IUserRepository))]IUserRepository oUserRepository, IRoleRepository oRoleRepository)
{
_userRepository = oUserRepository;
_roleRepository = oRoleRepository;
}
}
到底行不行呢?我们来测一把: 愿望是美好的,但异常是残酷的!看异常的具体信息:因为未能选择构造函数进行构造。请确保该类型具有默认构造函数或有一个标记有“System.ComponentModel.Composition.ImportingConstructorAttribute”的构造函数。很显然MEF的ImportingConstructorAttribute特性不支持这种多个构造函数同时标注的情况。将ImportingConstructorAttribute转到定义,发现它也没有其他可用属性 难道是博主的需求太奇葩啦?苦思良久,仍未找到解决方案。后来博主仔细想了想, 可能是侧重点的问题,MEF一般情况是和面向接口编程联系起来用的,也就是说正常情况下我们定义的是一个接口类型的变量,例如: [Import]
public IPowerManagerDomainService powerDomainService { get; set; }
它允许你有多个接口的实现类,如果你有多个构造函数的需求,完全可以一个接口写多个实现类去做,通过导入不同的实现类去代替不同的构造函数的用法 。也不知道园友有没有更好的解决方案?不吝赐教~~

  

MEF 注入[转载]的更多相关文章

  1. C#进阶のMEF注入

    1.什么是MEF 先来看msdn上面的解释:MEF(Managed Extensibility Framework)是一个用于创建可扩展的轻型应用程序的库. 应用程序开发人员可利用该库发现并使用扩展, ...

  2. 全面理解 ASP.NET Core 依赖注入 (转载)

    DI在.NET Core里面被提到了一个非常重要的位置, 这篇文章主要再给大家普及一下关于依赖注入的概念,身边有工作六七年的同事还个东西搞不清楚.另外再介绍一下.NET  Core的DI实现以及对实例 ...

  3. XML外部实体注入[转载]

    前言 对于xxe,深入的太少,一般做题也是复制payload再修改,没有了解过内部的结构规范等.这里转载了一篇先知社区的文章,排版了一下适合博客样式.文章总结的很好,结合了很多篇的博客文章,看完也是对 ...

  4. 使用Microsoft.Practices.Unity 依赖注入 转载https://www.cnblogs.com/slardar1978/p/4205394.html

    Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...

  5. .net自带的IOC容器MEF使用

    IOC能做什么 IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合.更优良的程序. 控制反转: 将控制权移交给第三方容器  new 操作 依赖注入: 在程序 ...

  6. sqlmap和burpsuite绕过csrf token进行SQL注入检测

    利用sqlmap和burpsuite绕过csrf token进行SQL注入 转载请注明来源:http://www.cnblogs.com/phoenix--/archive/2013/04/12/30 ...

  7. ASP.NET 5:依赖注入

    ASP.NET 5:依赖注入 1.背景 如果某个具体的(或类)对象被客户程序所依赖,通常把它们抽象成抽象类或接口.简单说,客户程序摆脱所依赖的具体类型,称之为面向接口编程. 那么问题来了?如何选择客户 ...

  8. 常见注入手法第二讲,APC注入

    常见注入手法第二讲,APC注入 转载注明出处 首先,我们要了解下什么是APC APC 是一个简称,具体名字叫做异步过程调用,我们看下MSDN中的解释,异步过程调用,属于是同步对象中的函数,所以去同步对 ...

  9. 把旧系统迁移到.Net Core 2.0 日记(3) - 详解依赖注入 (转)

    关于DI 依赖注入, 转载这篇文章, 写得很好的. ----------------------------- DI在.NET Core里面被提到了一个非常重要的位置, 这篇文章主要再给大家普及一下关 ...

随机推荐

  1. mysql查询哪个表数据量最大

    use information_schema;select table_name,table_rows from tables where table_schema='cargo_new' order ...

  2. hprose 1.0(rpc 框架) - 执行时序图

  3. Python之路--Python初识

    Python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆(中文名字:龟叔)为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程 ...

  4. Computer HDU - 2196

    Computer HDU - 2196 A school bought the first computer some time ago(so this computer's id is 1). Du ...

  5. Codeforces Round #472 A-D

    A题: 题意:就是给你一个长度为n的字符串,有三种颜色,其中有一些‘?’的字符代表未着色,你需要找到至少有两种方法染色,同时满足相邻两个字符间不能相同: 思路:有两种染色方法的前提:首先给定的字符串中 ...

  6. 笔记-python tutorial-9.classes

    笔记-python tutorial-9.classes 1.      Classes 1.1.    scopes and namespaces namespace: A namespace is ...

  7. Mybatis一个参数判断

    一:List<UserVo> list(@Param("nickName") String nickName); <select id="list&qu ...

  8. 16,Python网络爬虫之Scrapy框架(CrawlSpider)

    今日概要 CrawlSpider简介 CrawlSpider使用 基于CrawlSpider爬虫文件的创建 链接提取器 规则解析器 引入 提问:如果想要通过爬虫程序去爬取”糗百“全站数据新闻数据的话, ...

  9. IOS开发---菜鸟学习之路--(九)-利用PullingRefreshTableView实现下拉刷新

    本章主要讲解如何利用PullingRefreshTableView实现下拉(上拉)刷新的操作 PullingRefreshTableView 实现上下拉刷新的例子百度有很多,大家可以自己搜索下,先看下 ...

  10. PostgreSQL 行排序详解

    在查询生成输出表之后,也就是在处理完选择列表之后,你还可以对输出表进行排序. 如果没有排序,那么行将以不可预测的顺序返回(实际顺序将取决于扫描和连接规划类型和在磁盘上的顺序, 但是肯定不能依赖这些东西 ...