IOC的功能就是类似于简单工厂+配置文件 创建对象的效果差不多,只不过功能比之强大不少,慢慢往下看吧
IOS特点
1、控制反转:把对象的创建交给第三方容器来做
2、依赖注入:是一种具体的手段,注入的对象并不是我们自己主动创建的,而是容器创建的
注入的方式分为3种:
1、属性注入:直接在属性上加上[Dependency] 在容器创建该实例的时候,会自动赋值
2、方法注入:方法上添加[InjectionMethod] 只要方法上天津爱了这个特性,在容器创建这个方法的时候,会自动调用这个方法
3、构造函数注入:[InjectionConstructor]容器创建对象的时候会有限选择带这个特性的构造函数,会根据注册的类型,找到已经注册的参数创建传过来,如果去掉这个特性,会自动选取参数最多的构造函数
注:只要添加了特性之后,如果这个类型在Unity中并没有注册的话 会报错
[Dependency]//属性注入
public IHome firstHome { get; set; }
public IHome secondHome { get; set; }
public IHome thirdHome { get; set; }
public Chinese()
{
}
[InjectionConstructor]//构造函数注入 注:这个可有可无 如果没有 默认参数最多的一个构造函数
public Chinese(IHome home)
{
this.thirdHome = home;
}
public void Say()
{
Console.WriteLine("我是中国人");
}
[InjectionMethod]//方法注入
public void Init(IHome home)
{
this.secondHome = home;
}
Unity 是创建对象的第三方容器
要想使用Unity需要先引用以下dll
下面的这个是为了AOP用的
Unity创建对象
{
//创建没有依赖注入的
IUnityContainer container = new UnityContainer();
container.RegisterType<IPeople, Student>();
// 接口--类型 父类--子类 抽象类--子类
// container.RegisterInstance<IPeople>(new Student());//实例注册,和上面的注册方式 是一样的 不过这里可以在Student(参数)可以传递参数
IPeople people = container.Resolve<IPeople>();
}
{
//创建需要依赖注入的
IUnityContainer container = new UnityContainer();
container.RegisterType<IPeople, Chinese>();
container.RegisterType<IHome, home>();
IPeople people = container.Resolve<IPeople>();
}
{
//区别一个接口下的不同类型
IUnityContainer container = new UnityContainer();
container.RegisterType<IPeople, Chinese>("Chinese");
container.RegisterType<IPeople, Student>("Student");
container.RegisterType<IHome, home>();
IPeople people1 = container.Resolve<IPeople>("Chinese");
IPeople people2 = container.Resolve<IPeople>("Student");
}
{
//还可以设置 某种类型 是否生成单例
IUnityContainer container = new UnityContainer();
//container.RegisterType<IPeople, Chinese>(new TransientLifetimeManager());//瞬时 这种是默认的
container.RegisterType<IPeople, Chinese>(new ContainerControlledLifetimeManager());//容器单例
//container.RegisterType<IPeople, Chinese>(new PerThreadLifetimeManager());//线程单例
container.RegisterType<IHome, home>();
IPeople people2 = container.Resolve<IPeople>();
}
Unity+配置文件 创建对象
配置文件
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity>
<containers>
<!--普通配置 可以通过后面添加 name=“”区分不同类型-->
<container name="testContainer">
<!--type=接口命名空间,接口dll名称-->
<!--mapto要创建的类型的命名空间,要创建的类型的dll名称-->
<!--name=“”用来区分相同接口下的不同类型,如果没有必要 可以不写-->
<register type="Unity.Interface.IPeople,Unity" mapTo="Unity.Class.Chinese,Unity" name="Chinese"/>
<register type="Unity.Interface.IPeople,Unity" mapTo="Unity.Class.Student,Unity" name="Student"/>
<register type="Unity.Interface.IHome,Unity" mapTo="Unity.Class.home,Unity"/>
</container>
</containers>
</unity>
</configuration>
创建代码
下面是封装了一个通过配置文件创建对象的通用代码
private static IUnityContainer CreateUnity(string NodeName)
{
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config.xml");//找配置文件的路径
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
IUnityContainer container = new UnityContainer();
section.Configure(container, NodeName);
return container;
}
创建
IUnityContainer container= CreateUnity("testContainer");
IPeople people = container.Resolve<IPeople>("Chinese");
Unity 创建 AOP
配置文件
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity>
<!--下面这一句配置 是为了aop的 如果用不到可以不写-->
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
<containers>
<!--aop的配置-->
<container name="testContainerAOP">
<extension type="Interception"/><!--配置AOP需要添加此节点-->
<register type="Unity.Interface.IPeople,Unity" mapTo="Unity.Class.Chinese,Unity" name="Chinese">
<interceptor type="InterfaceInterceptor"/><!--扩展类型的dll-->
<interceptionBehavior type="Unity.AOP.LogBehavior, Unity"/> <!--aop方法-->
<!--lifetime生命周期 如 transient瞬时 containercontrolled容器单例 perthread线程单例-->
<lifetime type="transient" />
<constructor></constructor>
</register>
<register type="Unity.Interface.IPeople,Unity" mapTo="Unity.Class.Student,Unity" name="Student"/>
<register type="Unity.Interface.IHome,Unity" mapTo="Unity.Class.home,Unity"/>
</container>
<!--aop的配置-->
</containers>
</unity>
</configuration>
AOP方法
public class LogBehavior : IInterceptionBehavior
{
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("方法执行前");
IMethodReturn im= getNext().Invoke(input, getNext);
Console.WriteLine("方法执行后");
return im;
}
public bool WillExecute
{
get { return true; }
}
}
IUnityContainer container = CreateUnity("testContainerAOP");
IPeople people = container.Resolve<IPeople>("Chinese");
people.Say();
结果
Unity AOP之坑
在Unity配置文件创建AOP的时候,并不是默认调用参数最多的构造函数,而是去调用无参构造函数,解决办法是在配置文件中<constructor></constructor>节点里面添加参数配置
如想要调用下面这个构造函数
public Chinese(int id)
{
Console.WriteLine("有参构造{0}",id.ToString());
}
<constructor>
<param name="id" Type="System.Int32,mscorlib" value="3" />
<!--参数名称 参数命名空间+类型名称 dll名称 value=参数值-->
</constructor>
即可