依赖注入容器Autofac的详解

前端之家收集整理的这篇文章主要介绍了依赖注入容器Autofac的详解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

出处:http://www.renfb.com/blog/2011/Article/259

Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成,并且开源,Autofac的主要特性如下:

1,灵活的组件实例化:Autofac支持自动装配,给定的组件类型Autofac自动选择使用构造函数注入或者属性注入,Autofac还可以基于lambda表达式创建实例,这使得容器非常灵活,很容易和其他的组件集成。
2,资源管理的可视性:基于依赖注入容器构建的应用程序的动态性,意味着什么时候应该处理那些资源有点困难。Autofac通过容器来跟踪组件的资源管理。对于不需要清理的对象,例如Console.Out,我们调用ExternallyOwned()方法告诉容器不用清理。细粒度的组件生命周期管理:应用程序中通常可以存在一个应用程序范围的容器实例,在应用程序中还存在大量的一个请求的范围的对象,例如一个HTTP请求,一个IIS工作者线程或者用户的会话结束时结束。通过嵌套的容器实例和对象的作用域使得资源的可视化。
3,Autofac的设计上非常务实,这方面更多是为我们这些容器的使用者考虑:
●组件侵入性为零:组件不需要去引用Autofac。
●灵活的模块化系统:通过模块化组织你的程序,应用程序不用纠缠于复杂的XML配置系统或者是配置参数。
自动装配:可以是用lambda表达式注册你的组件,autofac会根据需要选择构造函数或者属性注入
●XML配置文件支持:XML配置文件过度使用时很丑陋,但是在发布的时候通常非常有用

Autofac的简单使用,并加入了Repository模式.

定义两个简单实体类:
publicclassPersion
{
publicstringName{get;set;}
publicintAge{get;set;}
}

publicclassCustom
{
publicstringCustomName{get;set;}
publicintCustomID{get;set;}
}


定义泛型数据库访问接口: publicinterfaceIdal<T>whereT:class { voidInsert(Tentity); voidUpdate(Tentity); voidDelete(Tentity); }

泛型数据库访问接口的泛型实现: publicclassDal<T>:Idal<T>whereT:class { #regionIdal<T>Members publicvoidInsert(Tentity) { HttpContext.Current.Response.Write("您添加了一个:" +entity.GetType().FullName); } publicvoidUpdate(Tentity) { HttpContext.Current.Response.Write("您更新一个:" +entity.GetType().FullName); } publicvoidDelete(Tentity) { HttpContext.Current.Response.Write("您删除了一个:" +entity.GetType().FullName); } #endregion }


使用Repository模式实现访问。
Repository的泛型接口: publicinterfaceIRepository<T>whereT:class { voidInsert(Tentity); voidUpdate(Tentity); voidDelete(Tentity); }

Repository泛型接口的泛型实现: publicclassRepository<T>:IRepository<T>whereT:class { privateIdal<T>_dal; publicRepository(Idal<T>dal) { _dal=dal; } #regionIRepository<T>Members publicvoidInsert(Tentity) { _dal.Insert(entity); } publicvoidUpdate(Tentity) { _dal.Update(entity); } publicvoidDelete(Tentity) { _dal.Delete(entity); } #endregion }

IDependency的依赖接口,不需要任何方法体,所有的业务对象都实现该接口 publicinterfaceIDependency { }

实现IDependency接口的CustomBll类,通过Repository模式存储数据。 publicclassCustomBll:IDependency { privatereadonlyIRepository<Custom>_repository; publicCustomBll(IRepository<Custom>repository) { _repository=repository; } publicvoidInsert(Customc) { _repository.Insert(c); } publicvoidUpdate(Customc) { _repository.Update(c); } publicvoidDelete(Customc) { _repository.Delete(c); } }

实现IDependency接口的PersionBll类,通过Repository模式存储数据。 publicclassPersionBll:IDependency { privatereadonlyIRepository<Persion>_repository; publicPersionBll(IRepository<Persion>repository) { _repository=repository; } publicvoidInsert(Persionp) { _repository.Insert(p); } publicvoidUpdate(Persionp) { _repository.Update(p); } publicvoidDelete(Persionp) { _repository.Delete(p); } }


下面编写组件实例化测试
varbuilder=newContainerBuilder(); builder.RegisterGeneric(typeof(Dal<>)).As(typeof(Idal<>)) .InstancePerDependency(); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)) .InstancePerDependency(); builder.Register(c=>newPersionBll((IRepository<Persion>) c.Resolve(typeof(IRepository<Persion>)))); builder.Register(c=>newCustomBll((IRepository<Custom>) c.Resolve(typeof(IRepository<Custom>)))); //varcontainer=builder.Build()教程里都是使用这行代码, //我本地测试需要加入ContainerBuildOptions枚举选项。 using(varcontainer=builder.Build(ContainerBuildOptions.None)) { //varrepository=container.Resolve(typeof(IRepository<Persion>),newTypedParameter()); //IRepository<Persion>_repository=repositoryasRepository<Persion>; //varm=newPersionBll(_repository); Persionp=newPersion(); p.Name="小人"; p.Age=27; varm=container.Resolve<PersionBll>(); m.Insert(p); Customc=newCustom(); c.CustomName="小小"; c.CustomID=10; varcc=container.Resolve<CustomBll>(); cc.Update(c); }


这里通过ContainerBuilder方法RegisterGeneric对泛型类进行注册(当然也可以通过ContainerBuilder方法RegisterType对不是泛型的类进行注册),当注册的类型在相应得到的容器中可以Resolve你的类实例。
builder.RegisterGeneric(typeof(Dal<>)).As(typeof(Idal<>)).InstancePerDependency();通过AS可以让类中通过构造函数依赖注入类型相应的接口。(当然也可以使用builder.RegisterType<类>().As<接口>();来注册不是泛型的类 )
Build()方法生成一个对应的Container实例,这样,就可以通过Resolve解析到注册的类型实例。

注:如果要获得某个泛型的实例,需要将泛型T代表的类传进去。如上c.Resolve(typeof(IRepository<Persion>))返回的是Object,需要转换为响应的接口。

当然可以使用autofac的新特性RegisterAssemblyTypes,从一个程序集的注册类型设置根据用户指定的规则,例子如下:
varbuilder=newContainerBuilder(); builder.RegisterGeneric(typeof(Dal<>)).As(typeof(Idal<>)).InstancePerDependency(); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerDependency(); //上面的那些类如果在单独的工程里,如生成的程序集为AutofacUnitTest,就可以使用 //Assembly.Load("AutofacUnitTest")获得响应的程序集。如果所有的文件在一个控制台程序里, //可以通过Assembly.GetExecutingAssembly(); 直接获得相应的程序集。 AssemblydataAccess=Assembly.Load("AutofacUnitTest"); builder.RegisterAssemblyTypes(dataAccess) .Where(t=>typeof(IDependency).IsAssignableFrom(t)&&t.Name.EndsWith("Bll")); //RegisterAssemblyTypes方法将实现IDependency接口并已Bll结尾的类都注册了,语法非常的简单。

猜你在找的设计模式相关文章