Castle Windsor: Can I get all instances of a type? - castle-windsor

I am registering a bunch of ITask implementations with Windsor using Named to separate them. Is there a way a class can request all instances of ITask?

Windsor can do what you request via the CollectionResolver subdependency resolver:
var container = new WindsorContainer();
var kernel = container.Kernel;
kernel.Resolver.AddSubResolver(new CollectionResolver(kernel));
Now, if you register multiple implementations of ITask, your task runner can have a ctor like this:
public TaskRunner(IEnumerable<ITask> tasks)
{
// ...
}
which is what you want, right?

Yes,
container.ResolveAll<ITask>()
This blog post explains in detail how to do it in a container ignorant way:
10 Advanced Windsor Tricks – 3. How to resolve arrays
Similar to the other answer given.

Related

Registering an Interceptor For All Interface Implementations in Castle Windsor

I'm fairly new to Castle Windsor and in particular using Interceptors and am wondering if it is possible to register an Interceptor across all implementations of a particular interface without specifying each implementation in turn. For example, I have an interface called IComponent which will be implemented by a number of classes. I have a ComponentInterceptor class written to act on these classes when they have executed a particular method. I would like to do something like:
_container.Register(
Component.For<IComponent>()
.Interceptors("ComponentInterceptor")
.LifestyleSingleton())
Rather than having to do:
_container.Register(
Component.For<IComponent>()
.ImplementedBy<ComponentA>()
.Interceptors("ComponentInterceptor")
.LifestyleSingleton()),
_container.Register(
Component.For<IComponent>()
.ImplementedBy<ComponentB>()
.Interceptors("ComponentInterceptor")
.LifestyleSingleton())
I found another approach, I wanted to register this interceptor for all components being registered and do this hopefully minimal fuss. To do this I follow this article and created a new class like this:
public class MyContributeComponentConstruct : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (model.Services.Any(s => s == typeof(IComponent)))
{
model.Interceptors.Add(InterceptorReference.ForType<ComponentInterceptor>());
}
}
}
and then add this contribute with the Castle Windsor container
container.Kernel.ComponentModelBuilder.AddContributor(new MyContributeComponentConstruct ());
You can register components in the container using conventions via the Classes class. The following registers all classes in the current assembly that implement IComponent under the service IComponent and with your ComponentInterceptor interceptor:
container.Register(
Classes.FromThisAssembly()
.BasedOn<IComponent>()
.WithService.FromInterface()
.Configure(c => c.Interceptors<ComponentInterceptor>())
);
The Windsor documentation provides a bunch of other examples and explains in detail what different classes are for.

IoC container that can register everything (non generic) automatically without configuration (assembly to assembly)

the idea is that I have a Core project with lots of interfaces, also Data and Service project with implementations (everything 1-to-1), e.g.:
Core { IFooRepo, IBarRepo, IFooService, IBarService}
Data {FooRepo: IFooRepo, BarRepo : IBarRepo}
Service {FooService : IFooService, BarService : IBarService}
so I would like something like
register(Core, Data);
register(Core, Service);
there are lots of IoC containers and I don't know which one of them can do this, or is closer to this solution, anybody knows ?
You are talking about auto-registration. Many IoC containers support this.
StructureMap
http://structuremap.net/structuremap/ScanningAssemblies.htm
Castle Windsor (see bottom of 2nd page of the article)
http://www.code-magazine.com/article.aspx?quickid=0906051
Autofac
http://code.google.com/p/autofac/wiki/Scanning
Ninject
Looks like you can do it via Kernel.Scan(), though I couldn't find docs. (Server was unavailable.)
How to use Ninject Conventions extension without referencing Assembly (or Types within it)
Last I looked, Unity did not support auto-registration, though that may have changed with a recent release.
UPDATE: Thanks to Mauricio for noticing that I incorrectly identified the desired feature as auto-wiring. Corrected and updated the links.
In Autofac the simplest way to achieve this is:
var builder = new ContainerBuilder();
var data = typeof(BarRepo).Assembly();
builder.RegisterAssemblyTypes(data).AsImplementedInterfaces();
var service = typeof(BarService).Assembly();
builder.RegisterAssemblyTypes(service).AsImplementedInterfactes();
var container = builder.Build();
Now this will not be selective about the service interfaces being from the Core assembly. If this really matters (it probably shouldn't) then vary the above registrations along these lines:
var core = typeof(IBarRepo).Assembly();
builder.RegisterAssemblyTypes(data)
.As(t => t.GetInterfaces()
.Where(i => i.Assembly == core)
.Select(i => new TypedService(i)));
Cheers,
Nick
Windsor lets you easily register classes as interfaces they expose, either all of them or, selectively. (see the documentation).
It does not have OOTB support for your scenario (filtering implemented interfaces to only include those from specific assembly) but (as for everything in Windsor) there's a hook you can use to easily have that.
container.Register(
AllTypes.FromAssemblyContaining<SomeClass>()
WithService.Select((type, #base) =>
type.GetAllInterfaces()
.Where(i => i.Assembly == yourInterfacesAssembly)))
);

Can you add a dependency to a Castle component that was auto-registered?

I generally use StructureMap, but on a current project I'm using Castle Windsor (2.1). I've found some code to auto-register types and interfaces:
_container.Register(AllTypes.Pick().FromAssembly(GetType().Assembly).WithService.FirstInterface());
However I would like to add a string dependency to one of the types. I can do this without the convention like this:
var registration = Component.For() .ImplementedBy().DependsOn(new[] { Property.ForKey("someString").Eq("blahblah") });
_container.Register(registration);
Is there any way I can do this with the auto-registered types?
you use ConfigureFor<> method which lets you finetune your registration on a granular level.

Castle Dynamic Proxy in Windsor Container

I've got a bit of a problem. I'm working in the Castle Windsor IOC Container. Now what i wanted to do is just mess about with some AOP principles and what i specifically want to do is based on a method name perform some logging. I have been looking at Interceptors and at the moment i am using the IInterceptor interface implemented as a class to perform this logging using aspects. The issue is if i want to perform the logging on a specific method then it gets messy as i need to put in some logic into my implemented aspect to check the method name etc...
I have read that you can do all of this using Dynamic Proxies and the IInterceptorSelector interface and the IProxyGenerationHook interface. I have seen a few examples of this done on the net but i am quite confused how this all fits into the Windsor container. I mean i am using the windsor container which in my code is actually a ref to the IWindsorContainer interface to create all my objects. All my configuration is done in code rather than XML.
Firstly does anyone know of a way to perform method specific AOP in the windsor container besides the way i am currently doing it.
Secondly how do i use the Dynamic Proxy in the windsor container ?
Below i have added the code where i am creating my proxy and registering my class with
the interceptors
ProxyGenerator _generator = new ProxyGenerator(new PersistentProxyBuilder());
IInterceptorSelector _selector = new CheckLoggingSelector();
var loggingAspect = new LoggingAspect();
var options = new ProxyGenerationOptions(new LoggingProxyGenerationHook())
{ Selector = _selector };
var proxy = _generator.CreateClassProxy(typeof(TestClass), options, loggingAspect);
TestClass testProxy = proxy as TestClass;
windsorContainer.Register(
Component.For<LoggingAspect>(),
Component.For<CheckLoggingAspect>(),
Component.For<ExceptionCatchAspect>(),
Component.For<ITestClass>()
.ImplementedBy<TestClass>()
.Named("ATestClass")
.Parameters(Parameter.ForKey("Name").Eq("Testing"))
.Proxy.MixIns(testProxy));
The Test Class is below:
public class TestClass : ITestClass
{
public TestClass()
{
}
public string Name
{
get;
set;
}
public void Checkin()
{
Name = "Checked In";
}
}
as for the interceptors they are very simple and just enter a method if the name starts with Check.
Now when i resolve my TestClass from the container i get an error.
{"This is a DynamicProxy2 error: Mixin type TestClassProxy implements IProxyTargetAccessor which is a DynamicProxy infrastructure interface and you should never implement it yourself. Are you trying to mix in an existing proxy?"}
I know i'm using the proxy in the wrong way but as i haven't seen any concrete example in how to use a proxy with the windsor container it's kind of confusing.
I mean if i want to use the LoggingProxyGenerationHook which just tell the interceptors to first for methods that start with the word "check" then is this the correct way to do it or am i completely on the wrong path. I just went down the proxy way as it seems very powerfull and i would like to understand how to use these proxies for future programming efforts.
By using .Interceptors() you already are using Dynamic Proxy. When component has specified interceptors Windsor will create proxy for it, and use these interceptors for it. You can also use method .SelectedWith and .Proxy property to set other options you already know from DynamicProxy.
I just added a website about Windsor AOP to documentation wiki. There's not much there yet, but I (and Mauricio ;) ) will put there all the information you need. Take a look, and let us know if everything is clear, and if something is missing.

How to get instance of service in Windsor Castle

In a multilayer application (ASP MVC: UI project, DAL project) i registered in web.config the components.
Now i have this problem: Unit of Work pattern has do be implemented and i need to get the current instance of a particular service. The registration of the services happened in the UI project, but i need to get the current instance of this service in the DAL project. How do i get this reference?
In the UI project i already needed a way to get something resolved:
container = new WindsorContainer(
new XmlInterpreter(new ConfigResource("castle"))
);
personRepository= container.Resolve<IPersonRepository>();
Would it be OK to use the same technique in the DAL project? If yes, should i write the configuration in a separate file, so that it can be accessed by all the layers(projects)?
Sorry for this (i think) naive question but it's my first project using Castle and i think i don't understand the big picture of it!
Code snippet would help a lot.
Thanks in advance!
In a nutshell: one container instance per application, one container configuration that has all the components you need for the application. If you need a service in your DAL, inject the appropriate service interface in your DAL class via constructor (if the dependency is required) or setter (if the dependency is optional).
Try really hard to avoid using a static IoC gateway, it hides the true dependencies of a component and it hampers testability.
See these related questions:
Usage of IoC Containers; specifically Windsor
Is it correct to have many Castle Windsor containers per application if those containers belong to different tiers?
Have a look at this article. It shows you how to write a static class that performs dependency resolution using Castle Windsor. You should consider putting this class in a separate project that can be referenced from both your UI and DAL projects to allow code reuse. As the article explains, your class should provide a bootstrapper facility that initializes your IoC container. In your case, this would look like:
public static class IoC
{
private WindsorContainer _container;
public static void Initialize()
{
_container = new WindsorContainer(
new XmlInterpreter(new ConfigResource("castle"))
);
}
}
The bootstrapper would be invoked from the application startup event in your UI projects Global.asax file.
The other methods for obtaining instances of objects from the container would be as per the article.