• Castle Windsor


    Part One- Getting Windsor

    通过Nuget引入Castle.Windsor

    Part Two- Plugging Windsor in 

    To get started using Windsor we need to plug it into the application.

    The first and most publicized MVC extension point that we'll look at is controller factory. We'll use it to have Windsor manage our controllers and all of their dependencies.

    通过Mvc 的公开扩展点ControllerFactory,通过它控制Controller和所有的依赖关系。

    Windsor Controller Factory

    In this part we created a controller factory which uses Windsor to manage components in our application.

    Controller factory的两个职责。

    (通过Container.IKernel) 为每个request创建新的Controller实例,请求结束后Release Controller实例

    为什么不使用IControllerActivator作为扩展点呢?因为它只有创建实例的方法,没有释放实例的方法。 Because it only has a Create method, and lacks method for releasing the controllers. 

    Part Three- Writing First Installer

    安装注册项目中的相关Compnent

    Windsor 使用Installer类(IWindsorInstaller) registration 程序中的Component(依赖组件、类)

    IWindsorInstaller只有一个方法 public void Install(IWindsorContainer container, IConfigurationStore store) ,参数container提供方法注册具体的Component

    注意:

    1.分类自己的WindsorInstaller,使它们保持简单,可读,职责单一,有利于测试和职责划分查找问题。

    2.By default Installers must be public with public default constructor

    Using installers

    FromAssembly

    container.Install(
       FromAssembly.This(),//在本程序集中安装
       FromAssembly.Named("Acme.Crm.Bootstrap"),//
       FromAssembly.Containing<ServicesInstaller>(),
       FromAssembly.InDirectory(new AssemblyFilter("Extensions")),
       FromAssembly.Instance(this.GetPluginAssembly())
    );
    安装程序集中所有个IWindsorInstaller
    注意:安装顺序不确定,需要确定安装顺序时使用InstallerFactory
    FromAssembly.This()
    在本程序集中安装
    FromAssembly.Named("Acme.Crm.Bootstrap")
    Install from assembly with specified assembly name using standard .NET assembly locating mechanism. 通过程序集名字注册
    You can also provide path to a .dll or .exe file when you have the assembly in some non-standard location.可以添加程序集的路径
    FromAssembly.Containing<ServicesInstaller>()
    在存在指定类的程序集中安装,和
    FromAssembly.Named 二选一。Installs from assembly containing designated type. This method is usually used as string-less alternative to FromAssembly.Named.
    FromAssembly.InDirectory(new AssemblyFilter("Extensions"))
    FromAssembly.Instance  
    InstallerFactory class 以上方法都有接受InstallerFactory参数的重载,通过它可以控制注册顺序、选择程序集中部分Installer进行注册。

    Configuration class 通过配置文件注册Installers
    container.Install(
       Configuration.FromAppConfig(),
       Configuration.FromXmlFile("settings.xml"),
       Configuration.FromXml(new AssemblyResource("assembly://Acme.Crm.Data/Configuration/services.xml"))
    );

    Part Four - Putting it All Together

    在Application_Start时

    container = new WindsorContainer().Install(FromAssembly.This());//创建容器
    var controllerFactory = new WindsorControllerFactory(container.Kernel);//创建ControllerFactory
    ControllerBuilder.Current.SetControllerFactory(controllerFactory);//设置当前ControllerFactory
    在Application_End时
    container.Dispose();//释放容器
     
     
     
     

    Lifestyles

    Singleton(default)

    第一次请求此Component时创建,以后重复使用。即使调用release也不会起作用,只会在container被释放时销毁。

    注意多线程时的状态,保证线程安全。

    Transient

    瞬时的,当使用它的对象released时,释放Component

    注意:如果使用container.Resolve<MyTransientComponent>()需要显示调用container.Release(myTransientInstance) 释放。

    Scoped

    eq:

    using Castle.MicroKernel.Lifestyle;
    using (Container.BeginScope()) //extension method
    {
    	var one = Container.Resolve<MyScopedComponent>();
    	var two = Container.Resolve<MyScopedComponent>();
    	Assert.AreSame(one, two);
    } // releases the instance.

    Bound

    PerThread

    Instance of a component will be shared in scope of a single thread of execution. 
    It will be created the first time the component is requested on given thread.
    Releasing the component explicitly does nothing.
    Instances will be released when the container they're registered with is disposed.
    单个线程内共享,只有container释放才会回收
    注意:Basically it should be used only when your application controls the thread, and never when thread pool threads (or Tasks) are involved.

    Pooled

    A pool of instances will be created and then one of them will be returned when requested. 
    When the component is first requested, the pool of initialSize elements is instantiated and a single one of them is marked internally as in use and returned.
    When more components are requested, the pool will first return all of the components it has that are not in use, and if it runs out, will start creating new ones.
    Releasing the components may do either of two things:
    1.
    When the pool has more components in use than maxSize the component will be released immediately
    2.Otherwise the component will be recycled (if it implements IRecyclable) and returned to the pool marked as ready to use.
    Windsor provides a special interface - Castle.Core.IRecyclable for poolable components.

    It contains single method: void Recycle();

    This method is invoked when the component is returned to the pool, and components can use it to implement custom initialization/clean up logic.

    Setting lifestyle

    API Setting
    Container.Register( Classes.FromThisAssembly() .BasedOn<IController>() .LifestyleTransient());

    XML Setting

    Simple components

    <components>
      <component
          id="notification"
          type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
      </component>
    </components>

    This is identical to specifying Component.For<EmailNotificationService>().Named("notification"); with Fluent Registration API.

    Component with abstraction

    <components>
      <component
          id="notification"
          service="Acme.Crm.Services.INotificationService, Acme.Crm"
          type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
      </component>
    </components>
    This is identical to specifying Component.For<INotificationService>().ImplementedBy<EmailNotificationService>().Named("notification");.

    Component with lifestyle

    <components>
      <component
          id="notification"
          service="Acme.Crm.Services.INotificationService, Acme.Crm"
          type="Acme.Crm.Services.EmailNotificationService, Acme.Crm"
          lifestyle="transient">
      </component>
    </components>

    The list of valid values for the lifestyle attribute (mapped to appropriate LifestyleManager enum values):

    LifestyleNotes
    singleton This is the default lifestyle in Windsor
    transient Windsor keeps references to transient components!
    pooled For pooled lifestyle two additional attributes need to be defined: initialPoolSize and maxPoolSize both of which accept positive integer values
    thread  
    custom For custom lifestyle additional attribute needs to be defined: customLifestyleType which points to the type implementing the lifestyle
    
    

    Component with parameters

    <components>
      <component
          id="notification"
          service="Acme.Crm.Services.INotificationService, Acme.Crm"
          type="Acme.Crm.Services.EmailNotificationService, Acme.Crm"
          lifestyle="transient">
        <parameters>
          <smtpServer>localhost:667</smtpServer>
          <senderEmail>#{admin.email}</senderEmail>
          <emailFormatter>${emailFormatter}</emailFormatter>
        </parameters>
      </component>
    </components>
    smtpServer is an inline parameter,也可以传递list、array、dictionary  or any other complex types 。(read more
    senderEmail is a property references ,its value is defined in the <properties> section of the configuration file (not shown here) under name admin.email. You specify property references using #{property.id}notation.
    emailFormatter is a service override parameter: as its value another component, registered with id equals emailFormatter will be used. You specify service overrides using ${service.id} notation.

    Component with multiple services (forwarded types)

    <components>
      <component
          id="notification"
          service="Acme.Crm.Services.INotificationService, Acme.Crm"
          type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
        <forwardedTypes>
          <add service="Acme.Crm.Services.IEmailSender, Acme.Crm" />
        </forwardedTypes>
      </component>
    </components>

    Setting properties

    By default when Windsor creates component it will try to set all its settable properties it can provide value for. 
    When using XML configuration this behavior can be adjusted.
    <component
          id="notification"
          service="Acme.Crm.Services.INotificationService, Acme.Crm"
          type="Acme.Crm.Services.EmailNotificationService, Acme.Crm"
          inspectionBehavior="none">
    </component>
     
    Inspection behaviorNotes
    all This is the default behavior
    none Windsor will not try to set any properties
    declaredonly Only properties declared on the component's type (and not ones declared on base types) will be set
     
    中文文档
    我的笔记

  • 相关阅读:
    MySQL索引的操作
    MySQL表的操作02
    MySQL表的操作01
    字典实现简单购物车程序
    python 中if和elif的区别
    格式化操作---%方法
    正则表达式相关知识
    实现 像网易云音乐 播放列表那样的弹出型Dialog
    为什么在非UI线程中操作UI的改变失不安全的
    模板方法模式-Template Method
  • 原文地址:https://www.cnblogs.com/fmys/p/9161783.html
Copyright © 2020-2023  润新知