惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Cyberwarzone
Cyberwarzone
S
Securelist
S
Schneier on Security
V
Vulnerabilities – Threatpost
Latest news
Latest news
G
GRAHAM CLULEY
C
CERT Recently Published Vulnerability Notes
T
The Exploit Database - CXSecurity.com
Scott Helme
Scott Helme
Know Your Adversary
Know Your Adversary
雷峰网
雷峰网
S
SegmentFault 最新的问题
Jina AI
Jina AI
A
About on SuperTechFans
GbyAI
GbyAI
F
Full Disclosure
T
Tenable Blog
博客园 - 聂微东
P
Privacy International News Feed
Recorded Future
Recorded Future
PCI Perspectives
PCI Perspectives
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
Microsoft Security Blog
Microsoft Security Blog
C
Check Point Blog
The GitHub Blog
The GitHub Blog
IT之家
IT之家
S
Secure Thoughts
Cloudbric
Cloudbric
S
Security @ Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园_首页
N
News | PayPal Newsroom
有赞技术团队
有赞技术团队
I
Intezer
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
大猫的无限游戏
大猫的无限游戏
The Register - Security
The Register - Security
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
Martin Fowler
Martin Fowler
小众软件
小众软件
人人都是产品经理
人人都是产品经理
C
Cyber Attacks, Cyber Crime and Cyber Security
宝玉的分享
宝玉的分享
Schneier on Security
Schneier on Security

博客园 - 永不言败

JavaScript 语言基础知识点总结(思维导图) 关于Visual Studio项目系统属性中的宏 MongoDb的相关资料 javascript apply 和call的区别,javascript设计模式 Adding a QR Code Reader in Flex on Android castle 在mvc3如何注入 Castle Automatic Transaction Management python webpy模板介绍 使用 asp.net mvc和 jQuery UI 控件包 webpy demo核心代码 Howto create a System.Linq.Expressions.Expression for Like 实体框架继承关系。很好 淘宝店铺图片数据迁移核心代码 mvc扩展 ASP.NET MVC 2 Templates C#、VB.NET使用HttpWebRequest访问https地址(SSL)的实现 Nhibernate继承 javaScript 运算符 && 和 || 的返回值 event.x,event.clientX,event.offsetX区别
Castle 容器注入学习例子
永不言败 · 2009-12-09 · via 博客园 - 永不言败

http://using.castleproject.org/display/IoC/Fluent+Registration+API

 http://developer.51cto.com/art/200907/139983.htm

http://blog.ploeh.dk/CategoryView,category,CastleWindsor.aspx

This is a scratchpad for documentation on Microkernel's fluent registration API. Please add anything you see fit and when it reaches a near-complete stage I will pull it out as a patch for the Castle documentation.

TODO (Stuff that could be documented)

  • explain service overrides
  • lifestyles
  • explain difference between 2 ways to supply parameters: string params using Parameters(...) & object params using DependsOn(...).
  • more AllTypes explanation
  • explain forwarding (Forward and Component.For<S,F1,F2 etc) )
  • explain Proxy and Interceptors() (what is the difference?)
  • explain Activator()
  • explain Configuration() and ExtendedProperties() (Configuration used for event wiring here: http://forum.castleproject.org/viewtopic.php?t=4999)
  • where is Overwrite() for? (I can see what is does in the code, but why would you use it?)
  • what does ActAs() do?

Introduction

The Registration API provides a fluent method of registering and configuring components. It can be used as an alternative or in addition to XML configuration, with the advantage that it is typed and will be easier to include in refactorings.

Requirements

Castle.Core, Castle.DynamicProxy2 and Castle.MicroKernel are all required. Chances are you'll be using Windsor so Castle.Windsor should be referenced too. You need to add a using directive to Castle.MicroKernel.Registration in order to use this API. The examples which follow assume you have created the Windsor Container thusly:

IWindsorContainer container = new WindsorContainer();

We will use the container instance throughout the API documentation.

Basic Registration Examples

The starting point for registering anything in the container is the container's Register() method, with has one or more IRegistration objects as parameter. The simplest way to create those objects is using the static Castle.MicroKernel.Registration.Component class. Its For() method returns a ComponentRegistration that you can use to further configure the registration.

To register a type in the container:

container.Register(
Component.For<MyServiceImpl>()
);

To register a type which implements a particular service:

container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
);

Note that For and ImplementedBy also have non-generic overloads.

// Same result as example above.
container.Register(
Component.For(typeof(IMyService)
.ImplementedBy(typeof(MyServiceImpl)
);

More information about services and components: http://www.castleproject.org/container/documentation/trunk/concepts/compsservices.html

To register a generic type:

Suppose you have a IRepository<TEntity> interface, with NHRepository<TEntity> as the implementation.

You could register a repository for each entity class, but this is not needed. One IRepository<> registration, without specifying the entity, is enough.

// Registering a repository for each entity is not needed.
//container.Register(
// Component.For<IRepository<Customer>>()
// .ImplementedBy<NHRepository<Customer>>(),
// Component.For<IRepository<Order>>()
// .ImplementedBy<NHRepository<Order>>(),
// and so on...
//);
// Does not work (compiler won't allow it):
//container.Register(
// Component.For<IRepository<>>()
// .ImplementedBy<NHRepository<>>()
//);
// Use typeof() and do not specify the entity:
container.Register(
Component.For(typeof(IRepository<>)
.ImplementedBy(typeof(NHRepository<>)
);

More information on generics support: http://www.castleproject.org/container/documentation/trunk/usersguide/genericssupport.html

Configuring the lifestyle for a type:

container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.LifeStyle.Transient
);

When the lifestyle is not set explicitly, the default Singleton lifestyle will be used.

More information about lifestyles: http://www.castleproject.org/container/documentation/trunk/usersguide/lifestyles.html

Register more components for the same service:

You can do this simply by having more registrations for the same service.

container.Register(
Component.For<IMyService>().ImplementedBy<MyServiceImpl>(),
Component.For<IMyService>().ImplementedBy<OtherServiceImpl>()
);

When a component has a dependency on IMyService, it will by default get the IMyService that was registered first (in this case MyServiceImpl). In Castle, the default implementation for a service is the first registered implementation. This is different from AutoFac for example, where the default is the last registered implementation (http://code.google.com/p/autofac/wiki/ComponentCreation).

Of course, you can override which implementation is used by a component that needs it. This is done with service overrides.

When you explicitly call container.Resolve<IMyService>() (without specifying the name), the container will also return the first registered component for IMyService (MyServiceImpl in the above example).

If you want to register the same implementation more than once, be sure to provide different names for the registered components.

To specify a name for the component:

The default name for a registered component is the full type name of the implementing type. You can specify a different name using the Named() method.

container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Named("myservice.default")
);

Supplying the component for a dependency to use (Service override)

If a component needs or wants an other component to function, this is called a dependency. When registering, you can explicitly set which component to use using service overrides.

container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Named("myservice.default"),
Component.For<IMyService>()
.ImplementedBy<OtherServiceImpl>()
.Named("myservice.alternative"),

Component.For<ProductController>()
.ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.alternative"))
);

public class ProductController
{
// Will get a OtherServiceImpl for myService.
// MyServiceImpl would be given without the service override.
public ProductController(IMyService myService)
{
}
}

See Strongly Typed property wiring with Fluent Registration API to get rid of strings when wiring properties of your component.

Supplying parameters in the form of strings

container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Parameters(
Parameter.ForKey("email").Eq("test@test.com")
)
);

Supplying parameters of other types

Many parameters are not strings, but some other type. But Parameters() only accepts string values, which can lead to formatting errors (with DateTime for example) and other problems. For these situations you can use the DependsOn() method. This method configures the component using objects of any type you like. DependsOn() accepts PropertyKeys (constructed using Property.ForKey()), a dictionary, or an anonymous object (which will be converted into a dictionary).

DateTime time2001 = new DateTime(2001, 2, 3, 18, 0, 0); // 6 o'clock, march 2nd 2001

// These registrations all configure the clock with the same parameter.
container.Register(
Component.For<IClock>().ImplementedBy<StaticClock>()
.Named("clock1")
.DependsOn(Property.ForKey("time").Eq(time2001)),
Component.For<IClock>().ImplementedBy<StaticClock>()
.Named("clock2")
.DependsOn(new {time = time2001}),
Component.For<IClock>().ImplementedBy<StaticClock>()
.Named("clock3")
.DependsOn(new Hashtable {{"time", time2001}})
);

See Strongly Typed property wiring with Fluent Registration API to get rid of strings when wiring properties of your component.

Using a delegate as component factory

You can use a delegate as a lightweight factory for a component (this requires the FactorySupportFacility to be installed):

container.Register(
Component.For<IMyService>()
.UsingFactoryMethod(() => MyLegacyServiceFactory.CreateMyService())
);

Registering Multiple Types at once

AllTypes is your friend. Here's an example from a Monorail configuration:

container.Register(
AllTypes.Of<SmartDispatcherController>()
.FromAssembly(Assembly.GetExecutingAssembly())
);

We are registering all types which implement SmartDispatcherController from the executing assembly. This is a quick way of adding all your controllers to the container.

AllTypes.Pick() is the same as AllTypes.Of<object>(), so it effectively selects all types.
AllTypes.Pick(IEnumerable<Type>) is a synonym for AllTypes.From(IEnumerable<Type>), i.e. it selects the specified types as registration targets.

Once you have selected the types you want to register, you can filter them based on each matched type.
For example, the following would match all the types implementing ICustomer in the current assembly only if the type name contains "Chain", so CustomerImpl would not be matched, but CustomerChain1 would:

AllTypes.Of<ICustomer>()
.FromAssembly(Assembly.GetExecutingAssembly())
.If(t => t.FullName.Contains("Chain"))

If we wanted to match types that don't contain "Chain":

AllTypes.Of<ICustomer>()
.FromAssembly(Assembly.GetExecutingAssembly())
.Unless(t => t.FullName.Contains("Chain"))

You might find somewhat surprising that any of the last two type selections would fail if you try to resolve a ICustomer:

container.Register(
  AllTypes.Of<ICustomer>()
    .FromAssembly(Assembly.GetExecutingAssembly())
);
container.Resolve<ICustomer>(); // FAILS with ComponentNotFoundException

In order to register the components with an interface as service type, you have to use the WithService modifier:

container.Register(
AllTypes.Of<ICustomer>()
.FromAssembly(Assembly.GetExecutingAssembly())
.WithService.FirstInterface()
);
container.Resolve<ICustomer>(); // OK

This instructs the container to use the first interface of each matched type as the service type.

Using with Xml Configuration

If you need to mix both styles of registration there are two options. If the Xml configuration can happen first, simply use the constructor overload that takes an Xml file name before using the fluent api for the rest.

IWindsorContainer container = new WindsorContainer("dependencies.config");

container.Register(
Component.For....
);

If the fluent registrations must happen first, add the following after all of your fluent calls.

container.Register(
Component.For....
);

container.Install(