Castle最早在2003年诞生于Apache Avalon项目,目的是为了创建一个IOC(控制反转)框架。发展到现在已经有四个组件了,分别是ActiveRecord(ORM组件),Windsor(IOC组件),DynamicProxy(动态代理组件),MonoRail(Web MVC组件)。
>> IOC-Castle Windor学习
一直想研究公司架构,不知从何下手,那就从Global开始吧,首先讲到的是Castle 注入,我在Word里面总结了下,就直接Copy过来了,代码测试正常,有看不懂的欢迎提问~
1.首先在Global里面进行注册:
private IWindsorContainer _container; //初始化一个IOC容器 _container= new WindsorContainer().Install(FromAssembly.This()); //完成IWindsorInstaller接口中的注册 ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container.Kernel));
2.需要自定义一个实例:
//在ASP.NET MVC中,每次请求,DefaultControllerFactory都会为我们创建controller实例,我们需要自定义一个派生自DefaultControllerFactory的类,让Castle Windsor帮我们生成controller实例。 using Castle.MicroKernel; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace Demo { public class WindsorControllerFactory : DefaultControllerFactory { private readonly IKernel _kernel; public WindsorControllerFactory(IKernel kernel) { _kernel = kernel; } protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, System.Type controllerType) { if (controllerType == null) { throw new HttpException(404, string.Format("当前对{0}的请求不存在", requestContext.HttpContext.Request.Path)); } return (IController)_kernel.Resolve(controllerType); } public override void ReleaseController(IController controller) { _kernel.ReleaseComponent(controller); base.ReleaseController(controller); } } }
3.声明一个类,定义依赖关系
public class TargetInstall : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register(Classes.FromThisAssembly() //在哪里找寻接口或类 .BasedOn<IController>() //实现IController接口 .If(Component.IsInSameNamespaceAs<HomeController>()) //与HomeController在同一个命名空间 .If(t => t.Name.EndsWith("Controller")) //以"Controller"结尾 .Configure(c => c.LifestylePerWebRequest()));//每次请求创建一个Controller实例 container.Register(Classes.FromThisAssembly() .Where(t=>t.Name.EndsWith("son")) .WithServiceDefaultInterfaces() .Configure(c=>c.LifestyleTransient()) ); } }
上面这个定义的依赖关系仅仅指定了以son结尾的Person类,如果在定义一个其他的不是以son结尾的类,那么就无法实现映射了,有局限性。 接下来修改为另一种方法做映射,这样只要按照指定规则在接口上面做标记就可以实现动态映射了。代码如下:
下面这段代码可以替换掉类TargetInstall 里面的以son结尾做映射的那段代码了:
var componentList = new List<IRegistration>(); var classes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.IsVisible).Where(p => ((ServiceAttribute)p.GetCustomAttributes(typeof(ServiceAttribute), false).FirstOrDefault()) != null).ToList(); foreach (var item in classes) { var name = item.FullName; var baseType = ((ServiceAttribute)item.GetCustomAttributes(typeof(ServiceAttribute), false).First()).BaseType; componentList.Add(Component.For(baseType).ImplementedBy(item).Named(name)); } container.Register(componentList.ToArray());
上面那段代码涉及到一个自定义类ServiceAttribute (这个类就是自定义一个属性)
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Demo { public class ServiceAttribute:Attribute { /// <summary> /// 设置或取得基类 /// </summary> public Type BaseType { get; set; } } }
最后在想要实现映射的类里面加标记就行了,比如Person类:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Demo { [Service(BaseType =typeof(IPerson))] public class Person : IPerson { public string Speak(string name) { return name; } } }
上面是使用代码直接注入,还可以通过配置文件注入,如下:
1.在Global里面进行注册:
//Castle配置文件注入 _container = new WindsorContainer(ConfigurationManager.AppSettings["IWindsorContainer"]); _container.Install(FromAssembly.This()); ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container.Kernel));//设置自定义控制工厂
2.进行Web配置:
<add key="IWindsorContainer" value="configcastle.xml" />
根据配置编写如下文件:
>>Castle.xml
<?xml version="1.0" encoding="utf-8" ?> <castle> <include uri="file://castle/components.config" /> </castle>
>>Components.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <components> <!--这里就写对应的接口和类,注意id别重复就行了--> <component id="GoldCRM.Domain.HXDataImport" service="Demo.IPerson,Demo" type="Demo.Person,Demo" > </component> </components> </configuration>
3.定义依赖关系:
public class ControllersInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { //实现IController接口 container.Register(Classes.FromThisAssembly() .BasedOn<IController>() .LifestyleTransient()); } }
4.需要自定义一个实例重写DefaultContgrollerFactory,参考上面即可:
--记得使用配置文件进行注册,每新增一个接口,要记得手动添加到配置文件哦~ 访问时就构造函数访问即可:
private IPerson person; public HomeController(IPerson person) { this.person=person; }
好了,Castle注入讲完了~
>>上面主要讲了Castle注入,既然说到这了,就接着上面把【拦截器】讲了吧:
拦截器可以在一个方法执行之前执行某些操作,并可以阻断方法的执行。
1.首先定义一个拦截器类:
public class ServiceInterceptor : IInterceptor { /// <summary> /// 拦截方法 /// </summary> /// <param name="invocation"></param> public void Intercept(IInvocation invocation) { invocation.Proceed(); } }
2.其次在继承IWindsorInstaller的类里面进行注册:,我就在TargetInstall里面直接写了(PS:按道理为了清晰,分工明确是应该单独建立一个类写的):
public class TargetInstall : IWindsorInstaller { private const string Interceptors = "Demo2.ServiceInterceptor"; public void Install(IWindsorContainer container, IConfigurationStore store) { //实现IController接口 container.Register(Classes.FromThisAssembly() .BasedOn<IController>() .LifestyleTransient()); //注册拦截器 container.Register(Classes.FromThisAssembly() .BasedOn<IInterceptor>()); //注册Service方法 var componentList = new List<IRegistration>(); var classes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.IsVisible).Where(p => ((ServiceAttribute)p.GetCustomAttributes(typeof(ServiceAttribute), false).FirstOrDefault()) != null).ToList(); foreach (var item in classes) { var name = item.FullName; var baseType = ((ServiceAttribute)item.GetCustomAttributes(typeof(ServiceAttribute), false).First()).BaseType; componentList.Add(Component.For(baseType).ImplementedBy(item).Named(name).Interceptors(Interceptors)); //Interceptors(Interceptors)这段是将拦截器注入 } container.Register(componentList.ToArray()); } }
Action拦截器参考:http://blog.csdn.net/gulijiang2008/article/details/7427223
好啦,拦截器就这么多啦,你运行的话,会发现先走拦截器再走方法哒~
接下来讲NHibernate学习→_→