Dashboard > MicroKernel/Windsor > Home > Fluent Registration API
Log In   View a printable version of the current page.
Fluent Registration API
Added by Colin Ramsay, last edited by Krzysztof Kozmic on Feb 24, 2010  (view change)
Labels: 


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.

Isolate your registration code

it is a recommended practice to keep your registration code in a dedicated class(es) implementing IWindsorInstaller.

Install infrastructure components first

Some components may require a facility or other extension to the core container to be registered properly. As such it is recommended that you always register your facilities, custom subsystems, Component model creation contributors etc before you start registering your components.

To register a type in the container:

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

This will register type MyServiceImpl as service MyServiceImpl with default lifestyle (Singleton).

To register a type as non-default 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.

// 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...
);

One IRepository<> (so called open generic type) registration, without specifying the entity, is enough.

// Does not work (compiler won't allow it):
container.Register(
    Component.For<IRepository<>>()
        .ImplementedBy<NHRepository<>>()
);

Doing it like this however is not legal, and the above code would not compile. Instead you have to use typeof()

// 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).

Provide unique names for duplicated components

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

Register existing instance:

It is possible to register an existing object as a service.

var customer = new CustomerImpl();
container.Register(
    Component.For<ICustomer>().Instance(customer)
    );

When you register an existing instance, even if you specify a lifestyle it will be ignored. Also registering instance, will set the implementation type for you, so if you  try to do it manually, an exception will be thrown.

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 before registering the components):
In the trunk version dependency on FactorySupportFacility has been removed, so that UsingFactory and UsingFactoryMethod will work as expected without the facility installed.

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

UsingFactoryMethod method has two more overloads, which can provide you with access to kernel, and creation context if needed.

Example of UsingFactoryMethod with kernel overload (Converter<IKernel, IMyService>)

 container.AddFacility<FactorySupportFacility>()
   .Register(
    Component.For<IMyFactory>().ImplementedBy<MyFactory>(),
    Component.For<IMyService>()
         .UsingFactoryMethod(kernel => kernel.Resolve<IMyFactory>().Create())
   );

In addition to UsingFactoryMethod method, there's a UsingFactory method. (without the "method" suffix  ). It can be regarded as a special version of UsingFactoryMethod method, which resolves an existing factory from the container, and lets you use it to create instance of your service.

container.Register(
    Component.For<User>().Instance(user),
    Component.For<AbstractCarProviderFactory>(),
    Component.For<ICarProvider>()
        .UsingFactory((AbstractCarProviderFactory f) => f.Create(container.Resolve<User>()))
    );


Avoid UsingFactory

It is advised to use UsingFactoryMethod, and to avoid UsingFactory when creating your services via factories. UsingFactory will be obsoleted/removed in future releases.

To inspect/modify instance created by the container before it's returned from the container:

It is sometimes needed to either inspect or modify created instance, before it is used. You can use OnCreate method to do this

 container.Register(
    Component.For<IService>()
        .ImplementedBy<MyService>()
        .OnCreate((kernel, instance) => instance.Name += "a")
    );

The method works with a delegate to which an IKernel and newly created instance are passed.

OnCreate works only for components created by the container

This method is not called for components where instance is provided externally (like when using Instance method). It is called only for components created by the container. This also includes components created via certain facilities (Remoting Facility, Factory Support Facility including components created via UsingFactory and UsingFactoryMethod methods).

In the trunk version UsingFactory and UsingFactoryMethod methods are excluded from that list. You should put your activation logic in them.

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)
    {
    }
}

Registering component with multiple services

 It is possible to use single component for more than one service. For example if you have a class FooBar which implements both IFoo and IBar interfaces, you can configure your container, to return the same service when IFoo and IBar are requested. This ability is called type forwarding.

Type forwarding

The easiest way to specify type forwarding is to use multi-generic-parameter overload of Component.For method

 container.Register(
    Component.For<IUserRepository, IRepository>()
        .ImplementedBy<MyRepository>()
    );

 There are overloads for up to four forwarded services, which should always be enough. If you find yourself needing more you most likely are violating Single Responsibility Principle, and you might want to break your giant component into more, each doing just one thing.

There's also a non-generic overload, which takes either IEnumerable<Type> or params Type[], in case you need open generics support or can't use generic version for whatever reason.

Moreover, you can use Forward method, which exposes identical behavior and overloads as For method.

container.Register(
    Component.For<IUserRepository>()
        .Forward<IRepository, IRepository<User>>()
            .ImplementedBy<MyRepository>()
    );

Supplying inline dependencies

 When registering components, you may want to supply some dependencies which are not services themselves. A good example would be the connection string. There are a couple of ways to do it, depending on your specific needs

 Supplying static dependencies

By static dependencies we mean those who have their value determined on the spot where we register them. The value does not change afterwards and is used every time a new instance of that  component gets created. 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.

Supplying XML-like parameters

Fluent API exposes yet another method of supplying inline dependencies - Parameters method. It is here mostly for legacy scenarios and most of the time it is advised to use DependsOn instead. It accepts either a string, or an IConfiguration object.

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

Parameters is direct equivalent of specifying <parameters /> in XML configuration. That's also the reason why it only accepts strings. Use it only when dealing with legacy code, that depends on the XML configuration. For all other scenarios using DependsOn is strongly advised. It is likely that in future release Parameters will be moved from client API, to API targetted at extending the container.

Supplying dynamic dependencies

There are times where you need to supply a dependency, which will not be known until the creation time of the component. For example, say you need a creation timestamp for your service. You know how to obtain it at the time of registration, but you don't know what its specific value will be (and indeed it will be different each time you create a new instance). In this scenarios you use DynamicParameters method.

container.Register(
    Component.For<ClassWithArguments>()
        .LifeStyle.Transient
        .DynamicParameters((k, d) => d["createdTimestamp"] = DateTime.Now)
    );

 DynamicParameters works with a delegate which is invoked at the very beginning of component resolution pipeline. It has two parameters: IKernel instance, and a dictionary with contains parameters supplied from the call site. Usually it will be empty. It is that dictionary that you can now populate with dependencies which will be passed further to the resolution pipeline.

Optionally you can also return a value from this method, being another delegate, which will be called at the end of your component's lifetime. You can use it to clean up the dependencies you supplied.

container.Register(
    Component.For<ClassWithArguments>()
        .LifeStyle.Transient
        .DynamicParameters((k, d) =>
        {
            d["arg1"] = "foo";
            return kk => ++releaseCalled;
        })
    );

Dynamic Service overrides

 Notice you can use DynamicParameters not only for non-service dependencies. It can also be used to specify dynamic service overrides:

 container.Register(
    Component.For<Service>()
        .LifeStyle.Transient
        .DynamicParameters((k, d) =>
        {
            var rng = k.Resolve<Random>();
            var randomNumber = rng.Next();
            if (randomNumber == 2)
            {
                d["customer"] = k.Resolve<ICustomer>("otherCustomer");
            }
        })
);

Registering Multiple Types at once

Registering types one by one can be very repetitive job. Also remembering to register each new type you add can quickly lead to frustration. Fortunately, you don't have to do it, at least always. By using AllTypes entry class you can perform group registration of types based on some specified characteristics you specify.

Registering all descendants of given type (for example all controllers in MVC application)

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. It will also automatically register all new controllers as you add them to your application.

Default Service

Keep in mind that Of as well as Pick and other filtering methods only narrow down the set of types we want to register. They do not specify the service that these types provide and unless you specify one the default will be used, that is the implementation type itself. In other words, the above registration will register all types inheriting from SmartDispatcherController with service being their own type, not the SmartDispatcherController so trying to call

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

will throw an exception.

In this default case types may be requested only by their implementation type (the default service).

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

Selecting source of types

container.Register(
    AllTypes.Of(typeof(ICommon))
        .FromAssembly(Assembly.GetExecutingAssembly())
    );

This registers all the public types implementing ICommon from specified assembly.

The above registration is limited to a single type of registration. The same registration can be expressed as

container.Register(
    AllTypes.FromAssembly(Assembly.GetExecutingAssembly())
         .BasedOn<ICommon>()
    );

As we will see below, this form of registration enables the ability to register multiple types in a single pass.

 Registering multiple types

 It is also possible, and recommended, to use the AllTypes strategy to efficiently register multiple selections based on different criteria.

container.Register(
    AllTypes.FromAssemblyContaining<DeleteCustomerCommand>()
        .BasedOn<IEntity>()
        .BasedOn<IHandler>()
    );/

In here, we register all types that implement either IEntity or IHandler interface in a single pass of the assembly using the implementation type as the service.

Registering generalizations

The examples above represent registrations in which the service type is not explicitly specified and thus defaults to the implementation.  There are several situations in which this is not sufficient.

container.Register(
    AllTypes.FromAssembly(Assembly.GetExecutingAssembly())
        .BasedOn(typeof(ICommand<>)).WithService.Base()
        .BasedOn(typeof(IValidator<>)).WithService.Base()
    );

Here we register all types implementing closed version of ICommand<> and IValidator<>, respectively (Now, read it again, slowly). To give you an example - when we request ICommand<AddCustomer> we'll receive an instance of type implementing ICommand<AddCustomer>, most likely named something like AddCustomerCommand.

The most important aspect of this specification, and often most confusing, is the presence of the WithService.Base(). This tells the registration strategy to choose the closed version of the interface specification as the service type. In this case, something like IValidator<Customer> might be selected. Without it, the type would be registered against the open version of the interface and you would most likely not get the desired resolution capability.

Another very common scenario is having the ability to register all types that share a common interface, but are otherwise unrelated.

container.Register(
    AllTypes.FromAssembly(Assembly.GetExecutingAssembly())
        .BasedOn<IService>().WithService.FromInterface()
    );

Here we register all types of services from the executing assembly. In this case, the IService interface might be a marker interface identifying the role of a component in the system. Unlike WithService.Base(), the service type selected for this registration is chosen from the interface that extended IService. The following is an example to help illustrate this.

Lets say you have a marker interface IService to designate all services in your assembly.

public interface IService {}

public interface ICalculatorService : IService
{
     float Add(float op1, float op2);
}

public class CalculatorService : ICalculatorService
{
     public float Add(float op1, float op2)
     {
         return op1 + op2;
     }
}

The above registration would be equivalent to

container.Register(
    Component.For<ICalculatorService>().ImplementedBy<CalculatorService>()
    );

As you can see, the actual service interface is NOT IService, but rather the interface extending IService, which is ICalculatorService in this case.

AllTypes.Pick(IEnumerable<Type>) is a synonym for AllTypes.From(IEnumerable<Type>) in which all object types are considered.

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(
    AllTypes.FromAssembly(Assembly.GetExecutingAssembly())
        .IncludeNonPublicTypes()
        .BasedOn<NonPublicComponent>()
    );

Notice that this option is available only if you call FromAssembly (or one of its sister methods, for example FromAssemblyContaining<TSomeType>) as the very first method on AllTypes.

It is rarely a good idea to expose via container types that wouldn't be available otherwise. Usually they are not public for a reason. Think twice before using this option.

Configuring registration

 When you register your types you can also configure them to set all the same properties as when registering types one by one. For this, you use configure method.

container.Register(
    AllTypes.Of<ICommon>()
        .FromAssembly(Assembly.GetExecutingAssembly())
        .Configure(
        component => component.LifeStyle.Transient
                         .Named(component.Implementation.FullName + "XYZ")
        )
    );

 In here we register all types implementing ICommon, set their lifestyle and name.

You can do also a more fine grained configuration, setting some additional properties for a subset of your components:

container.Register(
	AllTypes.Of<ICommon>()
		.FromAssembly(Assembly.GetExecutingAssembly())
		.Configure(
		component => component.LifeStyle.Transient
		             	.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)))
	);

 In here, we do the same thing as above, but in addition for types implementing two other interfaces we set additional inline dependencies.

 See the "Conditional component registration" section below for a discussion on better filtering the types you register.

Proxies

 Windsor/MicroKernel expose rich AOP abilities by using Castle Dynamic Proxy. // TODO: link to dynamic proxy and specific article discussing AOP in Windsor.

Interceptors

Interceptors are means to inject code around method's invocation.

Using Fluent API you can specify interceptors to use for specified components:

container.Register(
    Component.For<ICalcService>()
        .Interceptors(InterceptorReference.ForType<ReturnDefaultInterceptor>()).Last,
    Component.For<ReturnDefaultInterceptor>()
    );

Notice we register service for an interface without implementation. In this case, interceptor provides implementation for ICalcService's methods. We're using Explicit InterceptorReference to specify interceptors. By doing so we can specify where we want to put our interceptor in the interception pipeline. If we don't need that, we can use any of other overloads:

Selecting specific interceptors for specific methods

By default all interceptors you specify will be used for each interceptable method. To control which interceptors to use for which method you use InterceptorSelector (classes implementing IInterceptorSelector interface), which you can specify like this:

container.Register(
    Component.For<ICatalog>()
        .ImplementedBy<SimpleCatalog>()
        .Interceptors(InterceptorReference.ForType<DummyInterceptor>())
            .SelectedWith(new FooInterceptorSelector()).Anywhere,
    Component.For<DummyInterceptor>()
        );

Now FooInterceptorSelector will be called upon first call to each method to decide which interceptors should be used for that method.

Proxy options

In addition to specifying interceptors and interceptor selector, there's a number of other proxy-related options you can specify which are exposed via Proxy property. For example, you can use it to specify objects you want to mix in with your service:

container.Register(
    Component.For<ICalcService>()
        .ImplementedBy<CalculatorService>()
        .Proxy.MixIns(new SimpleMixIn())
    );

Proxies and AOP in Castle is much broader topic than presented here. To learn more about Dynamic Proxy that underpins it, read the following tutorial.

Conditional component registration

In cases when you want to register a component only if (or unless)  certain conditions are met, there are appropriate methods exposed in the API.

 Registering component only if it was not registered previously:

container.Register(
    Component.For(typeof(IRepository<>))
        .ImplementedBy(typeof(Repository<>))
        .Unless(Component.ServiceAlreadyRegistered)
        );

 Here we register component only if no component for IRepository<> was previously registered. Notice use of Component.ServiceAlreadyRegistered method in this context.

Filtering components in multiple components registration

Corresponding methods are exposed also when registering multiple components:

container.Register(
    AllTypes.Of<ICustomer>()
        .FromAssembly(Assembly.GetExecutingAssembly())
        .Unless(t => typeof(SpecificCustomer).IsAssignableFrom(t))
    );

 Here we register all types implementing ICustomer, except for SpecificCustomer and its descendants.

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

For better readability multiple service registration exposes additional filtering methods

 container.Register(
    AllTypes.FromAssembly(Assembly.GetExecutingAssembly())
        .Where(Component.IsInSameNamespaceAs<FooRepository>())
        .WithService.FirstInterface()
    );

You can also use Linq to do the filtering

container.Register(
    AllTypes.Of<CustomerChain1>()
        .Pick(from type in Assembly.GetExecutingAssembly().GetExportedTypes()
              where type.IsDefined(typeof(SerializableAttribute), true)
              select type
        )
    );

Notice what the above gives up - by virtue of putting a class in a specific namespace, inheriting from specific interface or having a specific attribute our components get registered and made available as services. We defined something very important here - conventions that free us from coding everything explicitly. This can't be overemphasized.

 Advanced topics

 If you've read (and understood) all of the above, you already know everything you need to know, to use Castle MicroKernel/Windsor containers. If you've explored the API (with Intellisense or Reflector) You'll notice that there are a couple of public methods, we haven't discussed yet. They are geared towards really advanced scenarios, and mostly used by facilities and other extensions to the container rather than by end users. As such feel free to skip this part, because it is very unlikely you will ever use any piece of API discussed here.

It is quite likely that the API discussed herein will be split from the client API and moved someplace else, to be explicitly targeted towards extension scenarios.

Component Descriptors / Attribute descriptors

Configuration API exposes AddDescriptor method that you can use to plug into ComponenModel creation lifetime. Objects passed to this method are then later invoked, having chance to modify created ComponentModel, and/or its IConfiguration object. In addition AddAttributeDescriptor and Attribute methods are exposed, which are equivalent, and are just a syntactic sugar over AddDescriptor, covering single, but quite common case - inserting key/value pair to component IConfiguration's Attributes collection. Descriptors are the main way used internally by container's fluent API, as well as most facilities to configure components.

Custom Component Activator

In Windsor/MicroKernel components are created by IComponentActivator objects. It is possible to supply your own to create your component using generic Activator method.

 Kernel.Register(
    Component.For<ICustomer>()
        .Named("customer")
        .ImplementedBy<CustomerImpl>()
        .Activator<MyCustomerActivator>()
    );

Notice that activator should be used only for creation of new instances of your objects. To decide when to create a new object, use ILifestyleManagers. Also some methods, like Instance, or some facilities you may use (FactorySupportFacility for example) set their own activators to perform the job. Keep that in mind, and do not use this method when using other activation mechanisms. Also take a look at OverWrite method.

Who wins?

What happens when two or more descriptors want to set the same attribute to different values? Which one will win? - The answer is - it depends. By default, as everywhere in Windsor - the first one wins. However you can turn it over, by enabling overwriting of already set values, by calling OverWrite method.

Currently this behavior is only exposed by LifestyleDescriptor (which sets the lifestyle manager) and attribute descriptor. Also be very careful when using this method. You should strive to not have to use it at all. It is very likely that it will be removed in the future releases.

Passing chunk of configuration

If you would like to pass an entire, bigger chunk of configuration all at once, you can use Configuration method of the Fluent API to do that. Generally doing it manually should be avoided, as it gets big and scary pretty quickly (here's real example from EventWiringFacility)

container.Register(
        Component.For<MessagePublisher>()
            .Configuration(
                Child.ForName("subscribers").Eq(
                    Child.ForName("subscriber").Eq(
                        Attrib.ForName("id").Eq("messageListener"),
                        Attrib.ForName("event").Eq("MessagePublished"),
                        Attrib.ForName("handler").Eq("OnMessagePublished")
                        )
                    )
                )
    );  

 Extended properties

 Non-configuration values, used by extensions are kept in extended properties, which is a flat bag of metadata attached to ComponentModel. It is generally not intended to be used by user code.

container.Register(
    Component.For<ICustomer>()
        .ImplementedBy<CustomerImpl>()
        .ExtendedProperties(
            Property.ForKey("key1").Eq("value1"),
            Property.ForKey("key2").Eq(2)
            )
        );

What does ActAs do?

ActAs is one of the most confusing methods in the API. Most notably it is used in WCF integration facility:

container.Register(
    Component.For<IServiceWithSession>()
        .ImplementedBy<ServiceWithSession>().LifeStyle.Transient
        .Named("Operations")
        .ActAs(new DefaultServiceModel().AddEndpoints(
                   WcfEndpoint.BoundTo(new NetTcpBinding { PortSharingEnabled = true })
                       .At("net.tcp://localhost/Operations")
                   )
        )
    );

 Semantically it is identical to DependsOn with only difference being, we don't specify the name of the dependency. In the above code we define WCF service implementation, which depends on DefaultServiceModel containing all the information WCF needs to run that service, but we don't care about the name of that dependency since it's not actual dependency of the ServiceWithSession object per se.

It is very likely that it will be removed in the future releases.

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(
    Configuration.FromXmlFile("dependencies.config"));
Site running on a free Atlassian Confluence Community License granted to Castle Project. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5.4 Build:#809 Jun 12, 2007) - Bug/feature request - Contact Administrators