示例①,日常使用:

 
 上壹篇小说学习了IL的入门,接下去大家再经过八个例证来明白下类的性质、构造函数以及接口的施用

金沙注册送58 , 
 上1篇文章学习了IL的入门,接下去大家再通过五个例子来打听下类的习性、构造函数以及接口的应用

Unity依赖注入使用详解 

有关定义:

一、类的本性、构造函数

1、类的品质、构造函数

写在眼前

  • 构造器注入
  • Dependency属性注入
  • InjectionMethod方法注入
  • 非泛型注入
  • 标识键
  • ContainerControlledLifetimeManager单例
  • Unity注册配置难题
  • Unity的app.config节点配置
  • 后记

关于 决定反转 (Inversion of Control)和 依附注入 (Dependency
Injection)大家英特网能够找下有关概念,在 《 菜肴学习设计形式(伍)—调控反转(Ioc)》 这篇作品中小编也有详细的批注,那边再作证下,有成千上万人把调控反转和注重注入混为一谈,即使在某种意义上来看他们是1环扣一环的,但类似又有点差异,就比方在上篇小说中所提到的演示。调控反转(Ioc)可以视作自来水厂,那自来水厂的运维就能够当做正视注入(DI),Ioc是3个调控容器,DI就是以此容器的运转搭飞机制,有点像国家主席和节制的意趣。

至于Ioc的框架有多数,举例astle
温泽、Unity、Spring.NET、StructureMap,大家那边使用微软提供的Unity做示范,你能够采用 Nuget 增添 Unity ,也足以引用Microsoft.Practices.Unity.dll和Microsoft.Practices.Unity.Configuration.dll,上面大家就一步一步的就学下 Unity正视注入 的详尽使用。

内容有点多,请坚持不渝往下看哦!

金沙注册送58 1金沙注册送58 2

一、先看下我们要创设的类的C#代码,然后再张开IL的贯彻,示例代码如下:

一、先看下大家要营造的类的C#代码,然后再拓展IL的落成,示例代码如下:

不能错过的Unity示例,IL接口和类的质量。构造器注入

构造器注入(Constructor
Injection):IoC容器会智能地选取选用和调用适合的构造函数以创办重视的目的。假如被增选的构造函数具有相应的参数,IoC容器在调用构造函数在此之前解析注册的依赖关系并机关获得对应参数对象。

经过地点的概念看以观看,使用构造器注入需求在在构造函数中传送多个虚无参数,Ioc会活动分析具象所凭仗的架空并登记给现实,大家照旧用上篇喝水视作示范:

金沙注册送58 3

 1 /// <summary>
 2         /// 人接口
 3         /// </summary>
 4         public interface IPeople
 5         {
 6             void DrinkWater();
 7         }
 8         /// <summary>
 9         /// 村民
10         /// </summary>
11         public class VillagePeople : IPeople
12         {
13             IWaterTool _pw;
14             public VillagePeople(IWaterTool pw)
15             {
16                 _pw = pw;
17             }
18             public void DrinkWater()
19             {
20                 Console.WriteLine(_pw.returnWater());
21             }
22         }
23         /// <summary>
24         /// 压水井
25         /// </summary>
26         public class PressWater : IWaterTool
27         {
28             public string returnWater()
29             {
30                 return "地下水好甜啊!!!";
31             }
32         }
33         /// <summary>
34         /// 获取水方式接口
35         /// </summary>
36         public interface IWaterTool
37         {
38             string returnWater();
39         }

View Code

代码很简短, Press沃特er注重于 I沃特erTool , 在 VillagePeople构造函数中传递1个 I沃特erTool 的架空,大家看下调用代码:

1         static void Main(string[] args)
2         {
3             UnityContainer container = new UnityContainer();//创建容器
4             container.RegisterType<Test01.IWaterTool, Test01.PressWater>();//注册依赖对象
5             Test01.IPeople people = container.Resolve<Test01.VillagePeople>();//返回调用者
6             people.DrinkWater();//喝水
7         }

运行结果:

金沙注册送58 4

上边根本用到Unity的RegisterType和Resolve的泛型方法,我们看下 RegisterType的 方法具名:

金沙注册送58 5

 1         //
 2         // 摘要:
 3         //     Register a type mapping with the container.
 4         //
 5         // 参数:
 6         //   container:
 7         //     Container to configure.
 8         //
 9         //   injectionMembers:
10         //     Injection configuration objects.
11         //
12         // 类型参数:
13         //   TFrom:
14         //     System.Type that will be requested.
15         //
16         //   TTo:
17         //     System.Type that will actually be returned.
18         //
19         // 返回结果:
20         //     The Microsoft.Practices.Unity.UnityContainer object that this method was
21         //     called on (this in C#, Me in Visual Basic).
22         //
23         // 备注:
24         //      This method is used to tell the container that when asked for type TFrom,
25         //     actually return an instance of type TTo. This is very useful for getting
26         //     instances of interfaces.
27         //     This overload registers a default mapping and transient lifetime.
28         public static IUnityContainer RegisterType<TFrom, TTo>(this IUnityContainer container, params InjectionMember[] injectionMembers) where TTo : TFrom;

View Code

我们能够看来RegisterType的首先个参数是 this IUnityContainer
container
 ,大家地方调用的时候并不曾传递一个IUnityContainer
类型的参数,为何那边会有二个this关键字,做哪些用?其实那就是 恢宏方法 。这几个扩展方法在静态类中声称,定义二个静态方法(UnityContainerExtensions类和RegisterType都以静态的),在这之中第二个参数定义可它的扩充项目。RegisterType方法扩张了UnityContainerExtensions类,因为它的首先个参数定义了IUnityContainer(UnityContainerExtensions的架空切口)类型,为了差别扩张方法和一般的静态方法,扩大方法还亟需给第四个参数使用this关键字。

再有就是RegisterType的泛型约束 where TTo :
TFrom; TTo必须是TFrom的派生类,便是说 TTo依赖于TFrom 。

大家再来看下Resolve泛型方法的签订契约:

金沙注册送58 6

 1         //
 2         // 摘要:
 3         //     Resolve an instance of the default requested type from the container.
 4         //
 5         // 参数:
 6         //   container:
 7         //     Container to resolve from.
 8         //
 9         //   overrides:
10         //     Any overrides for the resolve call.
11         //
12         // 类型参数:
13         //   T:
14         //     System.Type of object to get from the container.
15         //
16         // 返回结果:
17         //     The retrieved object.
18         public static T Resolve<T>(this IUnityContainer container, params ResolverOverride[] overrides);

View Code

“Resolve an instance of the default requested type from the
container”,那句话能够翻译为:消除从容器的私下认可请求的类别的实例,便是获取调用者的目标。

至于RegisterType和Resolve我们得以用自来水厂的例子来表达,请看上边:

  • RegisterType:能够视作是自来水厂决定用怎么样作为根本,能够是水库或是地下水,我假使“注册”开关一下就行了。
  • Resolve:能够看作是自来水厂要输送水的目的,能够是乡村或是城市,作者一旦“调节”输出就行了。
public interface ICar
{
    int Run();
}

public class BMW : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }
}

public class Ford : ICar
{
    private int _miles = 0;
    public int Run()
    {
        return ++_miles;
    }
}

public class Audi : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }

}
public class Driver
{
    private ICar _car = null;

    public Driver(ICar car)
    {
        _car = car;
    }

    public void RunCar()
    {
        Console.WriteLine("Running {0} - {1} mile ", _car.GetType().Name, _car.Run());
    }
}

金沙注册送58 7金沙注册送58 8

金沙注册送58 9金沙注册送58 10

Dependency属性注入

属性注入(Property
Injection):假设要求选取到被正视对象的有个别属性,在被依赖对象被创设之后,IoC容器会活动起初化该属性。

天性注入 只须求在品质字段前面加[Dependency]标志就行了,如下:

 1         /// <summary>
 2         /// 村民
 3         /// </summary>
 4         public class VillagePeople : IPeople
 5         {
 6             [Dependency]
 7             public IWaterTool _pw { get; set; }
 8             public void DrinkWater()
 9             {
10                 Console.WriteLine(_pw.returnWater());
11             }
12         }

调用格局和构造器注入同样,通过RegisterType<Test0贰.IWaterTool,
Test0②.Press沃特er>();注入就足以了,除了利用 RegisterType 方法注册,我们还是能够在计划文件中注册, [Dependency]和 RegisterType 方式实际上都会时有产生耦合度,大家要加多二特质量或是修改一中注册都会去修改代码,大家要做的就是代码不去修改,只要修改配置文件了,这些在底下有讲授,那边就不多说,我们先看下使用UnityConfigurationSection的Configure方法加载配置文件注册:

1   <unity>
2     <containers>
3       <container name="defaultContainer">
4         <register type="UnityContainerDemo.IWaterTool,UnityContainerDemo" mapTo="UnityContainerDemo.PressWater,UnityContainerDemo"/>
5         <register type="UnityContainerDemo.IPeople,UnityContainerDemo" mapTo="UnityContainerDemo.VillagePeople02,UnityContainerDemo"/>
6       </container>
7     </containers>
8   </unity>

调用代码:

1         public static void FuTest02()
2         {
3             UnityContainer container = new UnityContainer();//创建容器
4             UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
5             configuration.Configure(container, "defaultContainer");
6             IPeople people = container.Resolve<IPeople>();//返回调用者
7             people.DrinkWater();//喝水
8         }

运行结果:

金沙注册送58 11

View Code

    [Serializable]
    public class Dynamic
    {
        public int _a = 0;
        public const string ConstField = "const";

        /// <summary>
        /// 定义属性
        /// </summary>
        public int A { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="num"></param>
        public Dynamic(int num)
        {
            this.A = num;
        }

        public int Add(int num)
        {
            return this.A + num;
        }
    }
    [Serializable]
    public class Dynamic
    {
        public int _a = 0;
        public const string ConstField = "const";

        /// <summary>
        /// 定义属性
        /// </summary>
        public int A { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="num"></param>
        public Dynamic(int num)
        {
            this.A = num;
        }

        public int Add(int num)
        {
            return this.A + num;
        }
    }

InjectionMethod方法注入

艺术注入(Method
Injection):如若被依赖对象急需调用有个别方法开始展览相应的初步化,在该对象创造之后,IoC容器会活动调用该方式。

措施注入和总体性格局选拔同样, 方法注入 只须求在点子前加[InjectionMethod]标识就行了,从点子注入的概念上看,只是模糊的说对某些方法注入,并从未证实这么些法子所依附的对象注入,所依据的对象只是就二种:参数、再次回到值和办法内部对象引用,我们做3个示范试下:

 1     /// <summary>
 2     /// 村民
 3     /// </summary>
 4     public class VillagePeople03 : IPeople
 5     {
 6         public IWaterTool tool;//我是对象引用
 7         public IWaterTool tool2;//我是参数
 8         public IWaterTool tool3;//我是返回值
 9         [InjectionMethod]
10         public void DrinkWater()
11         {
12             if (tool == null)
13             { }
14         }
15         [InjectionMethod]
16         public void DrinkWater2(IWaterTool tool2)
17         {
18             this.tool2 = tool2;
19         }
20         [InjectionMethod]
21         public IWaterTool DrinkWater3()
22         {
23             return tool3;
24         }
25     }

调用代码:

 1         public static void FuTest03()
 2         {
 3             UnityContainer container = new UnityContainer();//创建容器
 4             UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
 5             configuration.Configure(container, "defaultContainer");
 6             VillagePeople03 people = container.Resolve<IPeople>() as VillagePeople03;//返回调用者
 7             Console.WriteLine("people.tool == null(引用) ? {0}", people.tool == null ? "Yes" : "No");
 8             Console.WriteLine("people.tool2 == null(参数) ? {0}", people.tool2 == null ? "Yes" : "No");
 9             Console.WriteLine("people.tool3 == null(返回值) ? {0}", people.tool3 == null ? "Yes" : "No");
10         }

container.Resolve<IPeople>() as 比利亚gePeople0三;其实小题大做,因为早已在配置文件注册过了,无需再进行中间转播,那边只是转账只是福利访问比利亚gePeople0叁对象的多少个属性值,我们看下运维效果:

金沙注册送58 12

结果确定,其实我们领略的秘诀注入正是对参数对象的流入,从typeConfig节点-method节点-param节点就可以看出来唯有参数的布局,而并不曾其余的布局,关于 typeConfig 下边会讲到。

使用:

View Code

View Code

非泛型注入

除了这一个之外大家地方使用RegisterType和Resolve泛型方法,大家也能够行使非泛型注入,代码如下:

1         public static void FuTest04()
2         {
3             UnityContainer container = new UnityContainer();//创建容器
4             container.RegisterType(typeof(IWaterTool), typeof(PressWater));//注册依赖对象
5             IPeople people = (IPeople)container.Resolve(typeof(VillagePeople01));//返回调用者
6             people.DrinkWater();//喝水
7         }

运作效果:

金沙注册送58 13

金沙注册送58 14金沙注册送58 15

二、通过上述代码大家能够根据须要先定义字段_a、常量ConstField(在构造函数进程中未利用到,帮组驾驭类属性的始建)以及给类加上连串化标签,属性能够通过TypeBuilder的DefineField创设,而连串化标签须要经过TypeBuilder的CustomAttributeBuilder去创建,示例代码如下:

贰、通过上述代码大家得以依靠须要先定义字段_a、常量ConstField(在构造函数进度中未使用到,帮组驾驭类属性的创建)以及给类加上类别化标签,属性可以由此TypeBuilder的DefineField创造,而类别化标签须求通过TypeBuilder的CustomAttributeBuilder去创建,示例代码如下:

标识键

小编们知晓,Unity提供了目的的容器,那么那些容器是怎么进展索引的吗?相当于说,容器内的单元是如何标记的呢?在Unity中,标志重要有二种艺术,
一种是一贯利用接口(恐怕基类)作为标志键,另一种是使用接口(或然基类)与名称的整合作为标志键,键对应的值正是具体类。

第1种选取接口(或许基类)作为标志键:

1 container.RegisterType<IWaterTool, PressWater>();

代码中的I沃特erTool便是作为标记键,你能够能够运用基类或是抽象类作为标记,获取注册对象:container.Resolve<I沃特erTool>(),若是1个Ioc容器容器里面注册了三个接口或是基类标示,大家再如此获取就不晓得注册的是哪3个?怎么化解,正是用接口或是基类与名称作为标记键,示例代码如下:

1         public static void FuTest05()
2         {
3             UnityContainer container = new UnityContainer();//创建容器
4             container.RegisterType<IWaterTool, PressWater>("WaterTool1");//注册依赖对象WaterTool1
5             container.RegisterType<IWaterTool, PressWater>("WaterTool2");//注册依赖对象WaterTool2
6             IWaterTool wt = container.Resolve<IWaterTool>("WaterTool1");//返回依赖对象WaterTool1
7             var list = container.ResolveAll<IWaterTool>();//返回所有注册类型为IWaterTool的对象
8         }

笔者们只需求在泛型方法RegisterType传入2个称号就足以来分别了(和挂号接口或基类),获取的话也只要传入注册时候的称号就能够,大家看下list中的集合对象:

金沙注册送58 16

var container = new UnityContainer();
container.RegisterType<ICar, BMW>();

var driver = container.Resolve<Driver>();
driver.RunCar();

金沙注册送58 17金沙注册送58 18

金沙注册送58 19金沙注册送58 20

ContainerControlledLifetimeManager单例

关于单例概念能够参照《 小菜学习设计格局(2)—单例(Singleton)形式》 那篇作品 , 为了贯彻单例方式,大家日常的做法是,在类中定义3个格局如GetInstance,判定若是实例为null则新建贰个实例,不然就回到已有实例。不过本身以为那种做法将目的的生命周期管理与类本人耦合在了一起。所以笔者觉着遇见要求运用单例的地方,应该将生命周期管理的天职转移到目的容器Ioc上,而笔者辈的类依旧是叁个深透的类,使用Unity成立单例代码:

1         public static void FuTest07()
2         {
3             UnityContainer container = new UnityContainer();//创建容器
4             container.RegisterType<IWaterTool, PressWater>(new ContainerControlledLifetimeManager());//注册依赖对象
5             IPeople people = container.Resolve<VillagePeople01>();//返回调用者
6             people.DrinkWater();//喝水
7         }

上边演示了将I沃特erTool注册为Press沃特er,并宣称为单例,ContainerControlledLifetimeManager字面意思上便是Ioc容器管理证明周期,咱们也足以不利用项目映射,将某些类注册为单例:

1 container.RegisterType<PressWater>(new ContainerControlledLifetimeManager());

除开将品种注册为单例,大家也得以将已有目标注册为单例,使用RegisterInstance方法,示例代码:

1 PressWater pw = new PressWater();
2 container.RegisterInstance<IWaterTool>(pw);

地点的代码就意味着将PressWater的pw对象注册到Ioc容器中,并声称为单例。

如果大家在登记类别的时候未有点名ContainerControlledLifetimeManager对象,Resolve获取的目的的生命周期是短暂的,Ioc容器并不会保留获取对象的引用,便是说大家再次 Resolve获取对象的时候,获取的是二个斩新的目的,借使我们钦点 ContainerControlledLifetimeManager ,类型注册后,我们重新 Resolve 获取的靶子正是上次创设的对象,而不是再重复创制对象,这也便是单例的情趣。

View Code

            //定义类可序列化
            CustomAttributeBuilder serializable = new CustomAttributeBuilder(typeof(SerializableAttribute).GetConstructor(Type.EmptyTypes), new Type[] { });
            typeBuilder.SetCustomAttribute(serializable);

            //定义常量
            FieldBuilder fieldConst = typeBuilder.DefineField("ConstField", typeof(string), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.Literal);
            fieldConst.SetConstant("const");

            //定义字段_a
            FieldBuilder aField = typeBuilder.DefineField("_a", typeof(int), FieldAttributes.Private);
            aField.SetConstant(0);
            //定义类可序列化
            CustomAttributeBuilder serializable = new CustomAttributeBuilder(typeof(SerializableAttribute).GetConstructor(Type.EmptyTypes), new Type[] { });
            typeBuilder.SetCustomAttribute(serializable);

            //定义常量
            FieldBuilder fieldConst = typeBuilder.DefineField("ConstField", typeof(string), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.Literal);
            fieldConst.SetConstant("const");

            //定义字段_a
            FieldBuilder aField = typeBuilder.DefineField("_a", typeof(int), FieldAttributes.Private);
            aField.SetConstant(0);

Unity注册配置难点

一发轫作者做的那示例是类类注册,正是说类富含类,全数的接口和目标都以位于TestXX类文件中,在配备register注册节点的时候,总是报上边错误:

金沙注册送58 21

或者

金沙注册送58 22

Unity配置文件:

1   <unity>
2     <containers>
3       <container name="defaultContainer">
4         <register type="UnityContainerDemo.Test02.IWaterTool,UnityContainerDemo" mapTo="UnityContainerDemo.Test02.PressWater,UnityContainerDemo"/>
5         <register type="UnityContainerDemo.Test02.IPeople,UnityContainerDemo" mapTo="UnityContainerDemo.Test02.VillagePeople,UnityContainerDemo"/>
6       </container>
7     </containers>
8   </unity>

第一个错误是“UnityContainer德姆o.Test0二.I沃特erTool,UnityContainer德姆o”未被辨认,第一个谬误是“UnityContainer德姆o”程序集无效,那种是行使UnityConfigurationSection情势注册的,使用RegisterType方法注册就没怎么难题,不知情是本人节点配置有标题,如故代码写的有难题,假使有知道的朋友,还请赐教,为了这么些主题素材,调节和测试了许久,最后无法把代码都独立放手。

大家选择Resolve来分析大家想要的调用对象,在这里是Driver。

View Code

View Code

Unity的app.config节点配置

上边所说的三种注入情势,包罗单例创造都以在代码中去安插的,当然只是演示用,那种布局都会生出耦合度,举例增加八脾质量注入或许艺术注入都要去属性或是艺术前加[Dependency]和[InjectionMethod]标志,大家想要的正视性注入应该是去布署文件中布局,当系统产生变化,大家不应去修改代码,而是在安排文件中期维修改,那才是真的使用重视注入化解耦合度所达到的效益,先看下Unity完整的布局节点:

金沙注册送58 23

上边的图我们兴许都见过,小编再贴一下Unity示例节点配置,原来的文章地址: msdn.microsoft.com/en-us/library/ff647848.aspx ,稍微翻译了下。

金沙注册送58 24

 1 <?xml version="1.0"?>
 2 <configuration>
 3   <configSections>
 4     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
 5              Microsoft.Practices.Unity.Configuration" />
 6   </configSections>
 7   <typeAliases>
 8     <!--寿命管理器类型-->
 9     <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,Microsoft.Practices.Unity" />
10     <typeAlias alias="external" type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity" />
11     <!--用户定义的类型别名-->
12     <typeAlias alias="IMyInterface" type="MyApplication.MyTypes.MyInterface, MyApplication.MyTypes" />
13     <typeAlias alias="MyRealObject" type="MyApplication.MyTypes.MyRealObject, MyApplication.MyTypes" />
14     <typeAlias alias="IMyService" type="MyApplication.MyTypes.MyService, MyApplication.MyTypes" />
15     <typeAlias alias="MyDataService" type="MyApplication.MyTypes.MyDataService, MyApplication.MyTypes" />
16     <typeAlias alias="MyCustomLifetime" type="MyApplication.MyLifetimeManager, MyApplication.MyTypes" />
17   </typeAliases>
18   <unity>
19   <containers>
20     <container name="containerOne">
21       <types>
22         <!--类型映射无一生-默认为“瞬时”-->
23         <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass" />
24         <!--使用上面定义的别名类型的映射-->
25         <type type="IMyInterface" mapTo="MyRealObject" name="MyMapping" />
26         <!--使用类型别名指定的终身-->
27         <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass">
28           <lifetime type="singleton" />
29         </type>
30         <type type="IMyInterface" mapTo="MyRealObject" name="RealObject">
31           <lifetime type="external" />
32         </type>
33         <!--使用完整的类型名指定终身经理-->
34         <!--的一生经理指定的任何初始化数据-->
35         <!--将要使用的默认类型转换器转换-->
36         <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass">
37           <lifetime value="sessionKey" type="MyApplication.MyTypes.MyLifetimeManager,MyApplication.MyTypes" />
38         </type>
39         <!--使用一个自定义TypeConverter的终身管理器初始化-->
40         <type type="IMyInterface" mapTo="MyRealObject" name="CustomSession">
41           <lifetime type="MyCustomLifetime" value="ReverseKey" typeConverter="MyApplication.MyTypes.MyTypeConverter,MyApplication.MyTypes" />
42         </type>
43         <!--对象在配置中定义的注入参数-->
44         <!--使用上面定义的别名类型的映射-->
45         <type type="IMyService" mapTo="MyDataService" name="DataService">
46           <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
47             <constructor>
48               <param name="connectionString" parameterType=

示例二,八个注入:

三、通过TypeBuilder的DefineProperty定义属性A,通过CustomAttributeBuilder给属性增多对应的竹签,示例代码如下:

3、通过TypeBuilder的DefineProperty定义属性A,通过CustomAttributeBuilder给属性增多对应的标签,示例代码如下:

有关定义的代码不改变,将使用一些的代码改为:

金沙注册送58 25金沙注册送58 26

金沙注册送58 27金沙注册送58 28

金沙注册送58 29金沙注册送58 30

            //定义属性A
            PropertyBuilder propertyABuilder = typeBuilder.DefineProperty("A", PropertyAttributes.None, typeof(int), null);
            CustomAttributeBuilder desAttributeBuilder = new CustomAttributeBuilder(typeof(DescriptionAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "属性A" });
            propertyABuilder.SetCustomAttribute(desAttributeBuilder);//字段描述
            //定义属性A
            PropertyBuilder propertyABuilder = typeBuilder.DefineProperty("A", PropertyAttributes.None, typeof(int), null);
            CustomAttributeBuilder desAttributeBuilder = new CustomAttributeBuilder(typeof(DescriptionAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "属性A" });
            propertyABuilder.SetCustomAttribute(desAttributeBuilder);//字段描述
var container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>("LuxuryCar");

// Register Driver type            
container.RegisterType<Driver>("LuxuryCarDriver", 
                new InjectionConstructor(container.Resolve<ICar>("LuxuryCar")));

Driver driver1 = container.Resolve<Driver>();// injects BMW
driver1.RunCar();

Driver driver2 = container.Resolve<Driver>("LuxuryCarDriver");// injects Audi
driver2.RunCar();

View Code

View Code

View Code

4、定义A属性的get方法和set方法,get和set方法和平常的措施创制一样,用TypeBuilder的DefineMethod创立。示例代码如下:

4、定义A属性的get方法和set方法,get和set方法和日常的章程创设同样,用TypeBuilder的DefineMethod创造。示例代码如下:

示例三,四个构造函数参数:

金沙注册送58 31金沙注册送58 32

金沙注册送58 33金沙注册送58 34

连带定义:

            //定义属性get方法
            MethodBuilder methodABuilder = typeBuilder.DefineMethod("get", MethodAttributes.Public, typeof(Int32), Type.EmptyTypes);
            ILGenerator GetIL = methodABuilder.GetILGenerator();
            GetIL.Emit(OpCodes.Ldarg_0);
            GetIL.Emit(OpCodes.Ldfld, aField);
            GetIL.Emit(OpCodes.Ret);
            propertyABuilder.SetGetMethod(methodABuilder);

            //定义属性set方法
            MethodBuilder methodBBuilder = typeBuilder.DefineMethod("set", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(Int32) });
            ILGenerator SetIL = methodBBuilder.GetILGenerator();
            SetIL.Emit(OpCodes.Ldarg_0);
            SetIL.Emit(OpCodes.Ldarg_1);
            SetIL.Emit(OpCodes.Stfld, aField);
            SetIL.Emit(OpCodes.Ret);
            propertyABuilder.SetSetMethod(methodBBuilder);
            //定义属性get方法
            MethodBuilder methodABuilder = typeBuilder.DefineMethod("get", MethodAttributes.Public, typeof(Int32), Type.EmptyTypes);
            ILGenerator GetIL = methodABuilder.GetILGenerator();
            GetIL.Emit(OpCodes.Ldarg_0);
            GetIL.Emit(OpCodes.Ldfld, aField);
            GetIL.Emit(OpCodes.Ret);
            propertyABuilder.SetGetMethod(methodABuilder);

            //定义属性set方法
            MethodBuilder methodBBuilder = typeBuilder.DefineMethod("set", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(Int32) });
            ILGenerator SetIL = methodBBuilder.GetILGenerator();
            SetIL.Emit(OpCodes.Ldarg_0);
            SetIL.Emit(OpCodes.Ldarg_1);
            SetIL.Emit(OpCodes.Stfld, aField);
            SetIL.Emit(OpCodes.Ret);
            propertyABuilder.SetSetMethod(methodBBuilder);

金沙注册送58 35金沙注册送58 36

View Code

View Code

public interface ICarKey { 

}

public class BMWKey : ICarKey 
{

}

public class AudiKey : ICarKey 
{

}

public class FordKey : ICarKey 
{

}

public class Driver
{
    private ICar _car = null;
    private ICarKey _key = null;

    public Driver(ICar car, ICarKey key) 
    {
        _car = car;
        _key = key;
    }

    public void RunCar()
    {
        Console.WriteLine("Running {0} with {1} - {2} mile ", _car.GetType().Name , _key.GetType().Name,  _car.Run());
    }
}

伍、构造函数的创造,构造函数是因此TypeBuilder的DefineConstructor去获得,构造函数包罗三个参数并赋值给_a,示例代码如下:

五、构造函数的创造,构造函数是由此TypeBuilder的DefineConstructor去赚取,构造函数包括八个参数并赋值给_a,示例代码如下:

View Code

金沙注册送58 37金沙注册送58 38

金沙注册送58 39金沙注册送58 40

相关应用:

            //定义构造函数
            ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Int32) });

            ILGenerator constructorIL = constructorBuilder.GetILGenerator();
            constructorIL.Emit(OpCodes.Ldarg_0);
            constructorIL.Emit(OpCodes.Ldarg_1);
            constructorIL.Emit(OpCodes.Stfld, aField);
            constructorIL.Emit(OpCodes.Ret);
            //定义构造函数
            ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Int32) });

            ILGenerator constructorIL = constructorBuilder.GetILGenerator();
            constructorIL.Emit(OpCodes.Ldarg_0);
            constructorIL.Emit(OpCodes.Ldarg_1);
            constructorIL.Emit(OpCodes.Stfld, aField);
            constructorIL.Emit(OpCodes.Ret);

金沙注册送58 41金沙注册送58 42

View Code

View Code

var container = new UnityContainer();

container.RegisterType<ICar, Audi>();
container.RegisterType<ICarKey, AudiKey>();

var driver = container.Resolve<Driver>();
driver.RunCar();

六、最终是定义方法。

六、最终是定义方法。

View Code

金沙注册送58 43金沙注册送58 44

金沙注册送58 45金沙注册送58 46

示例4,多少个构造函数:

            //定义方法
            MethodBuilder methodAddBuild = typeBuilder.DefineMethod("Add", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(int) });
            ILGenerator addIL = methodAddBuild.GetILGenerator();
            addIL.Emit(OpCodes.Ldarg_0);
            addIL.Emit(OpCodes.Ldfld, aField);
            addIL.Emit(OpCodes.Ldarg_1);
            addIL.Emit(OpCodes.Add);
            addIL.Emit(OpCodes.Ret);
            //定义方法
            MethodBuilder methodAddBuild = typeBuilder.DefineMethod("Add", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(int) });
            ILGenerator addIL = methodAddBuild.GetILGenerator();
            addIL.Emit(OpCodes.Ldarg_0);
            addIL.Emit(OpCodes.Ldfld, aField);
            addIL.Emit(OpCodes.Ldarg_1);
            addIL.Emit(OpCodes.Add);
            addIL.Emit(OpCodes.Ret);

连锁定义不改变,将运用部分代码改为:

View Code

View Code

金沙注册送58 47金沙注册送58 48

到这一步叁个动态类包涵的本性、构造函数以及艺术就创办达成。能够借助reflector看下生成的结果。如下:

到这一步三个动态类包括的天性、构造函数以及艺术就创建完毕。能够借助reflector看下生成的结果。如下:

public class Driver
{
    private ICar _car = null;

    [InjectionConstructor]
    public Driver(ICar car)
    {
        _car = car;
    }

    public Driver(string name)
    {
    }

    public void RunCar()
    {
        Console.WriteLine("Running {0} - {1} mile ", _car.GetType().Name, _car.Run());
    }
}

金沙注册送58 49

金沙注册送58 50

View Code

public int A { get; set; }
换成
public int A5
{
get { return _a; }
set { _a = value; }
}
比较容易理解_a的存在
public int A { get; set; }
换成
public int A5
{
get { return _a; }
set { _a = value; }
}
比较容易理解_a的存在

金沙注册送58 51金沙注册送58 52

 贰、接口的实现

 二、接口的贯彻

container.RegisterType<Driver>(new InjectionConstructor(new Ford()));

//or 

container.RegisterType<ICar, Ford>();
container.RegisterType<Driver>(new InjectionConstructor(container.Resolve<ICar>()));

1、首先大家看下大家要达成贰个怎么样的接口,先看下创设类的C#代码,示例代码如下:

一、首先大家看下大家要兑现四个哪些的接口,先看下营造类的C#代码,示例代码如下:

View Code

金沙注册送58 53金沙注册送58 54

金沙注册送58 55金沙注册送58 56

示例伍,基类型作为构造函数参数:

    public class Mail : IMail
    {

        public string SendMail()
        {
            return "Send Success";
        }
    }

    public interface IMail
    {
        string SendMail();
    }
    public class Mail : IMail
    {

        public string SendMail()
        {
            return "Send Success";
        }
    }

    public interface IMail
    {
        string SendMail();
    }

相关定义:

View Code

View Code

金沙注册送58 57金沙注册送58 58

二、达成接口,接口我们直接用IMail那么些。就毫无IL去创设了,首先大家成立三个typeBuilder,钦定继承继口IMail,能够用AddInterfaceImplementation来拓展操作。示例代码如下:

二、落成接口,接口大家平昔用IMail这几个。就不要IL去创立了,首先大家创设二个typeBuilder,钦定继承接口IMail,能够用AddInterfaceImplementation来进展操作。示例代码如下:

public class Driver
{
    private ICar _car = null;
    private string _name = string.Empty;

    public Driver(ICar car, string driverName)
    {
        _car = car;
        _name = driverName;
    }

    public void RunCar()
    {
        Console.WriteLine("{0} is running {1} - {2} mile ", 
                        _name, _car.GetType().Name, _car.Run());
    }
} 

金沙注册送58 59金沙注册送58 60

金沙注册送58 61金沙注册送58 62

View Code

            //定义类型
            TypeBuilder typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public);
            typeBuilder.AddInterfaceImplementation(typeof(IMail));
            //定义类型
            TypeBuilder typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public);
            typeBuilder.AddInterfaceImplementation(typeof(IMail));

有关应用:

View Code

View Code

金沙注册送58 63金沙注册送58 64

叁、落成接口。接口完毕方式要怎么定义在不知道的气象下得以用reflector反编写翻译八个贯彻接口的点子来查阅一下,观望一下办法须要如何MethodAttributes属性。

三、完成接口。接口达成方式要怎么定义在不亮堂的事态下得以用reflector反编写翻译多少个兑现接口的格局来查阅一下,观察一下主意须求哪些MethodAttributes属性。

var container = new UnityContainer();

container.RegisterType<Driver>(new InjectionConstructor(new object[] { new Audi(), "Steve" }));

var driver = container.Resolve<Driver>(); // Injects Audi and Steve
driver.RunCar();

金沙注册送58 65

金沙注册送58 66

View Code

透过以上消息能够定义接口达成的秘技,接口达成就和前面例子定义的章程落成平等。示例代码如下:

由此上述音讯能够定义接口落成的方式,接口落成就和在此以前例子定义的法子达成平等。示例代码如下:

全体请参考:

金沙注册送58 67金沙注册送58 68

金沙注册送58 69金沙注册送58 70

            MethodBuilder sendMailBuilder = typeBuilder.DefineMethod("SendMail", MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(string), null);
            //定义接口
            ILGenerator mailIL = sendMailBuilder.GetILGenerator();
            LocalBuilder resultStr = mailIL.DeclareLocal(typeof(String));
            mailIL.Emit(OpCodes.Nop);
            mailIL.Emit(OpCodes.Ldstr, "Send Success1");
            mailIL.Emit(OpCodes.Stloc_0);
            mailIL.Emit(OpCodes.Ldloc_0);
            mailIL.Emit(OpCodes.Ret);
            MethodBuilder sendMailBuilder = typeBuilder.DefineMethod("SendMail", MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(string), null);
            //定义接口
            ILGenerator mailIL = sendMailBuilder.GetILGenerator();
            LocalBuilder resultStr = mailIL.DeclareLocal(typeof(String));
            mailIL.Emit(OpCodes.Nop);
            mailIL.Emit(OpCodes.Ldstr, "Send Success1");
            mailIL.Emit(OpCodes.Stloc_0);
            mailIL.Emit(OpCodes.Ldloc_0);
            mailIL.Emit(OpCodes.Ret);

View Code

View Code

福寿康宁后经过IL查看的代码如下:

贯彻后经过IL查看的代码如下:

金沙注册送58 71

金沙注册送58 72

 
反编写翻译开掘,接口落成是带有override关键字的。而在概念完毕格局时候假设不带上virtual属性又会提醒接口未达成。。。。。。

 
反编写翻译发掘,接口达成是富含override关键字的。而在概念达成格局时候假设不带上virtual属性又会唤起接口未落成。。。。。。

 
通过那篇文章大家精晓到了动态类的创始,也询问到了接口的行使。从那五个示范其实能够拓展出多数的事物比方承袭、属性绑定自定义标签、虚方法的重写……以往再逐1分享
演示代码下载:IL-3

 
通过这篇小说大家精晓到了动态类的制造,也询问到了接口的使用。从那五个示范其实能够开始展览出无数的事物举个例子持续、属性绑定自定义标签、虚方法的重写……现在再逐一分享
演示代码下载:IL-3

相关文章

网站地图xml地图