Thứ Hai, 22 tháng 12, 2014

Castle Windsor: How to Register Components

You can register your components in the following ways:
  • Registering components one-by-one (Read More)
  • Registering components by conventions (Read more)
  • Registering components using Xml configuration, which can be combined with the code options (Read more)

Registering components one-by-one

1
2
3
4
5
6
// Initialize the container
var container = new WindsorContainer();
// Register your component with the desired lifestyle
container.Register(Component.For<IComponent>()
                       .ImplementedBy<Component>()
                       .LifestylePerThread());

What about open generic types?

1
2
3
4
5
// Initialize the container
var container = new WindsorContainer();
// Register your component for instance with the default lifestyle = Singleton
container.Register(Component.For(typeof (IRepository<>)
                       .ImplementedBy(typeof (Repository<>));

How to replace an allready registered component?

In Windsor you can simple register it again, the last registered component will be the one used

1
2
3
4
5
6
7
8
9
10
// Initialize the container
var container = new WindsorContainer();
// Register your component for instance with a lifestyle
container.Register(Component.For(typeof (IRepository<>)
                       .ImplementedBy(typeof (Repository<>)
                       .LifestylePerWebRequest());
// Register a specialized CustomerRepository
container.Register(Component.For<IRepository<Customer>>()
                       .ImplementedBy<CustomerRepository>()
                       .LifestylePerWebRequest());

How to make one class resolvable by two interface but have them share the same instance?

1
2
3
4
5
6
// Initialize the container
var container = new WindsorContainer();
// Register your component
container.Register(Component.For<IRepository<Customer>, ICustomerRepository>()
                       .ImplementedBy<CustomerRepository>()
                       .LifestylePerWebRequest());

How can i use the decorator pattern?

First let’s create a logging decorator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class LoggingCustomerRepository : IRepository<Customer>
{
   public ILogger Logger { get; set; };
   public IRepository<Customer> Repository { get; private set; }
   public LoggingCustomerRepository(IRepository<Customer> repository)
   {
      this.Repository = repository;
   }
   public Customer this[int id]
   {
      get { return Repository[id]; }
   }
   public void Add(Customer instance)
   {
      logger.Debug("Adding customer");
      Repository.Add(instance);
   }
}
With Castle Windsor the order of the registrations enables this behavior, so the first implementation will be injected into the decorator.

1
2
3
4
5
6
7
8
9
10
// Initialize the container
var container = new WindsorContainer();
// Register the default implementation
container.Register(Component.For<IRepository<Customer>()
                       .ImplementedBy<CustomerRepository>()
                       .LifestylePerWebRequest());
// Now register the decorator
container.Register(Component.For<IRepository<Customer>()
                       .ImplementedBy<LoggingCustomerRepository>()
                       .LifestylePerWebRequest());

Registering components by conventions

To do exactly the same but with conventions syntax

1
2
3
4
5
6
7
// Initialize the container
var container = new WindsorContainer();
// Register all non abstract class inheriting from IRepository with all interfaces
// as service, so resolvable by all interfaces
container.Register(Classes.FromThisAssembly()
                       .BasedOn(typeof(IRepository<>))
                       .WithServiceAllInterfaces());
WithServiceAllInterfaces: Means windsor will register the component bound to all it’s interfaces, so if for instance your CustomerRepository implements IRepository but also ICustomerRepository, when you resolve an instance, it will be shared across both contracts for the specified lifetime ( transient means no sharing )

Using installers

Installers provide you a way to group related registrations into one class, to create an installer simply create a class and implement IWindsorInstaller, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
namespace Windsor.Tests.Generics
{
   public class RepositoryInstaller : IWindsorInstaller
   {
      public void Install(IWindsorContainer container, IConfigurationStore store)
      {
         container.Register(Classes.FromThisAssembly()
                               .BasedOn(typeof(IRepository<>))
                               .WithServiceAllInterfaces());
      }
   }
}
To use this installer simple install it on your container instance

1
2
3
4
// Initialize the container
var container = new WindsorContainer();
// Install the installer(s)
container.Install(new RepositoryInstaller());

Không có nhận xét nào: