zoukankan      html  css  js  c++  java
  • IOC-Castle Windsor映射

    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学习→_→

  • 相关阅读:
    查看CLOUD系统级IIS日志
    采购订单设置采购部门为缺省值
    单据头数据复制到单据体
    CLOUD设置过滤方案不共享
    BZOJ 4773: 负环 倍增Floyd
    LOJ #539. 「LibreOJ NOIP Round #1」旅游路线 倍增floyd + 思维
    BZOJ 4821: [Sdoi2017]相关分析 线段树 + 卡精
    一些常用公式/技巧
    BZOJ 4517: [Sdoi2016]排列计数 错排 + 组合
    BZOJ 3162: 独钓寒江雪 树的同构 + 组合 + 计数
  • 原文地址:https://www.cnblogs.com/shuai7boy/p/7246626.html
Copyright © 2011-2022 走看看