castle windsor学习-----Registering components by conventions

注册多个组件

1.one-by-one注册组件可能是一项非常重复的工作,可以通过Classes或Types注册一组组件(你可以指定一些特定的特征)

三个步骤

注册多个类型通常采取以下结构

container.Register(Classes.FromThisAssembly()
    .InSameNamespaceAs<RootComponent>()
    .WithService.DefaultInterfaces()
    .LifestyleTransient());

 

 可以看成三个不同的步骤

1)选择程序集

  第一步指定Windsor要扫描的程序集,可以使用如下方法(或者使用它的姊妹方法)

Classes.FromThisAssembly()...

 

2)选择要扫描的程序集后,你可以筛选一些类型来注册,选择下面三种方式

  a. 通过基类型或者实现的接口

    

Classes.FromThisAssembly().BasedOn<IMessage>()

  b. 通过命名空间筛选类型

Classes.FromAssemblyInDirectory(new AssemblyFilter("bin")).InNamespace("Acme.Crm.Extensions")

 

  c. 通过任何一个条件筛选

Classes.FromAssemblyContaining<MyController>().Where( t=> Attribute.IsDefined(t, typeof(CacheAttribute)))

 

  d. 获取所有的类型

Classes.FromAssemblyNamed("Acme.Crm.Services").Pick()

 

 

附加过滤和配置

通过上面筛选到了类型源,你也可以给它们添加额外的配置或过滤条件,下面我们讨论所有的api使用

BaseOn、Where、Pick 如果使用多次需谨慎

container.Register(
    Classes.FromThisAssembly()
        .BasedOn<IMessage>()
        .BasedOn(typeof(IMessageHandler<>)).WithService.Base()
        .Where(Component.IsInNamespace("Acme.Crm.MessageDTOs"))
);

 

注册所有子类

container.Register(
    Classes.FromThisAssembly()
        .BasedOn<SmartDispatcherController>()
        .Configure(c => c.Lifestyle.Transient)
);

 

记住  Of 、Pick和其他过滤方法只是缩小注册类型的范围

他们没有指定服务的提供者,也就是说上面的注册只是注册继承了SmartDispatcherController服务的自己类型,SmartDispatcherController并没有被注册

所以调用如下方法将出现异常

var controller = container.Resolve<SmartDispatcherController>();

 

 

选择组件的服务

默认的 组件的服务就是类型本身,一些场景下这是不够的,Windsor让你指定明确的服务类型

Base()

container.Register(
    Classes.FromThisAssembly()
        .BasedOn(typeof(ICommand<>)).WithService.Base(),
    Classes.FromThisAssembly()
        .BasedOn(typeof(IValidator<>)).WithService.Base()
);

 

这里我们注册了所有实现ICommand<>和IValidator的类型。

DefaultInterfaces()

container.Register(
    Classes.FromThisAssembly()
        .InNamespace("Acme.Crm.Services")
        .WithService.DefaultInterfaces()
);

 

FromInterface()

container.Register(
    Classes.FromThisAssembly()
        .BasedOn<IService>().WithService.FromInterface()
);

 

 

AllInterfaces()

When a component implements multiple interfaces and you want to use it as a service for all of them, use WithService.AllInterfaces() method.

Self()

To register the component implementation type explicitly as a service use WithService.Self()

Select()

If none of the above options suits you you can provide your own selection logic as a delegate and pass it to WithService.Select() method.

Registering non-public types

By default only types visible from outside of the assembly will be registered. If you want to include non-public types, you have to start with specifying assembly first, and then call IncludeNonPublicTypes

container.Register(
    Classes.FromThisAssembly()
        .IncludeNonPublicTypes()
        .BasedOn<NonPublicComponent>()
);

  

Configuring registration

 

container.Register(
    Classes.FromAssembly(Assembly.GetExecutingAssembly())
        .BasedOn<ICommon>()
        .Configure(component => component.LifestyleTransient())
);
container.Register(
    Classes.FromAssembly(Assembly.GetExecutingAssembly())
        .BasedOn<ICommon>()
        .LifestyleTransient()
);
container.Register(
    Classes.FromAssembly(Assembly.GetExecutingAssembly())
        .BasedOn<ICommon>()
        .LifestyleTransient()
        .Configure(component => component.Named(component.Implementation.FullName + "XYZ"))
);
container.Register(
    Classes.FromThisAssembly()
        .BasedOn<ICommon>()
        .LifestyleTransient()
        .Configure(
            component => component.Named(component.Implementation.FullName + "XYZ")
        )
        .ConfigureFor<CommonImpl1>(
            component => component.DependsOn(Property.ForKey("key1").Eq(1))
        )
        .ConfigureFor<CommonImpl2>(
            component => component.DependsOn(Property.ForKey("key2").Eq(2))
        )
);
container.Register(
    Classes.FromThisAssembly()
        .BasedOn<ICommon>()
        .LifestyleTransient()
        .Configure(
            component => component.Named(component.Implementation.FullName + "XYZ")
        )
        .ConfigureIf(
            x => x.Implementation.Name.StarsWith("Common"),
            component => component.DependsOn(Property.ForKey("key1").Eq(1))
        )
);

 

 

 

posted @ 2017-03-11 19:19  蓝平凡  阅读(559)  评论(0编辑  收藏  举报