Castle Windsor, selecting service implementation depending on some context parameters - castle-windsor

With Castle Windsor 3.2
I need to resolve service implementation on the fly depending on contextual parameters.
Here is basic example of what I want to do:
I have a service IFoo
public interface IFoo
{
object GetSomething();
}
Implemented by 2 different classes Foo1 and Foo2
public class FooBase
{
public int Number {get; private set;}
public FooBase(int number)
{
Number = number;
}
}
public class Foo1 : IFoo
{
public Foo1(int number):base(number)
public object GetSomething()
{
return "Foo1";
}
}
public class Foo2 : IFoo
{
public Foo2(int number):base(number)
public object GetSomething()
{
return "Foo2";
}
}
I want to call the castle windsor resolve method with number as parameter, and depending on the number I want to have Foo1 or Foo2 object:
var foo1 = container.Resolve<IFoo>(new {number= 1});
// foo1 is Foo1
var foo2 = container.Resolve<IFoo>(new {number= 2});
// foo2 is Foo2
I tried several potential solutions, but I'm realy confused because of the lack of Castle Windsor documentation and examples, adding to that most of the examples are not up to date and are using obsolete API.
So I have seen some example using the following concepts, but none of them seemed to much my requirement :
HandlerSelector
Typed Factory facility
UsingFactoryMethod

Here is the code that worked for me:
container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<IFoo>().ImplementedBy<Foo1>().Named("Foo1"),
Component.For<IFoo>().ImplementedBy<Foo2>().Named("Foo2"),
Component.For<IFooFactory>().AsFactory(c => c.SelectedWith<FooSelector>())
);
Create a Foo factory :
public interface IFooFactory
{
IFoo CreateFoo(int number);
}
and a selector:
public class FooSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(System.Reflection.MethodInfo method, object[] arguments)
{
var argument = (int) arguments[0];
return string.Format("Foo{0}", argument);
}
}

use the following registration code:
container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<FooSelector>,
Component.For<Foo1>(),
Component.For<Foo2>(),
Component.For<IFooFactory>().AsFactory(c => c.SelectedWith<FooSelector>())
);
Create a Foo factory :
public interface IFooFactory
{
IFoo CreateFoo(int number);
}
and a selector:
public class FooSelector : DefaultTypedFactoryComponentSelector
{
protected override Type GetComponentType(System.Reflection.MethodInfo method, object[] arguments)
{
var argument = (int) arguments[0];
if (argument == 1) return typeof (Foo1);
if (argument == 2) return typeof(Foo2);
throw new ApplicationException();
}
}
Now resolve the IFooFactory and call the create methode with the value that you want.
Kind regards,
Marwijn.

Related

How to register an interface for interceptions

I want to register an interface like: IInterceptingAware, so that for all classes which implement this interface an interceptor class is used.
public class InterceptorClass : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// Do my work
}
}
public class Foo : IInterceptingAware
{
}
public class Bar : IInterceptingAware
{
}
How do I setup castle windsor for this?
using (var container = new WindsorContainer())
{
container.Register(
Component.For<MyInterceptorClass>(),
Classes.FromThisAssembly()
.BasedOn<IInterceptingAware>()
.WithServiceDefaultInterfaces()
.ConfigureFor<IInterceptingAware>(c => c.Interceptors<MyInterceptorClass>())
);
var foo = container.Resolve<Foo>();
foo.Test();
var bar = container.Resolve<IBar>();
bar.Test();
}
Console.ReadLine();
Keep in mind interceptor requires at least virtual methods on target class, even better your target class should implement an interface in order to have the interceptor working on that contract.
Said so, your Foo class should at least have a method named Test marked as virtual
while Bar should implement IBar:
public interface IBar
{
void Test();
}

ninject factory constructor selection with runtime generics

How can I use a ninject factory, which creates an instance with constructor parameters, without relying on the argument names.
The problem is that the ToConstructor()-Method not works, because I bind it to a generic definition.
The following example works, if I use the factory method with the corresponding constructor argument name, but I don't like it rely on names.
Because the following solution is very fragil and breaks if someone chooses a wrong name or renames the ctor-argument in the derived class.
Any solution?
Here's the example code:
[TestFixture]
public class NinjectFactoryBindingsTest
{
[Test]
public void ConstructorSelectionWithArguments()
{
NinjectSettings ninjectSettings = new NinjectSettings();
ninjectSettings.LoadExtensions = false;
using (var kernel = new StandardKernel(ninjectSettings, new FuncModule()))
{
// IDependencyA will be passed to the factory, therefore it is not bounded
//kernel.Bind<IDependencyA>().To<DependencyA>();
kernel.Bind<IDependencyB>().To<DependencyB>();
kernel.Bind(typeof(IGenericBaseClass<>)).To(typeof(GenericDerivedClass<>));
kernel.Bind<IGenericClassFactory>().ToFactory();
IGenericClassFactory factory = kernel.Get<IGenericClassFactory>();
DependencyA dependencyA = new DependencyA();
IGenericBaseClass<GenericImpl> shouldWorkInstance = factory.Create<GenericImpl>(dependencyA);
Assert.NotNull(shouldWorkInstance);
}
}
}
public interface IGenericClassFactory
{
IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA someName) where TGeneric : IGeneric;
// This works, but relies on ctor-param-names!!!
// IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA otherNameThanInBaseClass) where TGeneric : IGeneric;
}
public class DependencyA : IDependencyA
{
}
public class DependencyB : IDependencyB
{
}
public class GenericDerivedClass<TGeneric> : GenericBaseClass<TGeneric> where TGeneric : IGeneric
{
public GenericDerivedClass(IDependencyA otherNameThanInBaseClass, IDependencyB dependencyB)
: base(otherNameThanInBaseClass, dependencyB)
{
}
}
public abstract class GenericBaseClass<TGeneric> : IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
protected GenericBaseClass(IDependencyA dependencyA, IDependencyB dependencyB)
{
}
}
public interface IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
}
public interface IDependencyB
{
}
public interface IDependencyA
{
}
public class GenericImpl : IGeneric
{
}
public interface IGeneric
{
}
The factory extension has the convention that arguments must have the same name as the constructor argument they will be passed to. There are no easy ways to do it differently. The only way I can think of is about the following:
Create a new IParameter implementation that can hold a reference to an IDependencyA.
Create either a hardcoded factory or a custom IInstanceProvider (see documentation) that creates an instance of your IParameter implementation so that it is passed to the Get<> request
Add a new binding for IDependencyA: Bind<IDependency>().ToMethod(ctx => extract and return your parameter from the context)

Change ServiceOverride after component registration in Castle

I have two components registered for a service:
container.Register(
Component.For<IDataStorage>().Named("FirstChoice").ImplementedBy...
Component.For<IDataStorage>().Named("SecondChoice").ImplementedBy
Then I have a set of components deriving from this base class, that depends on those components:
public abstract class BaseMessageHandler
{
public IDataStorage FirstStorage {get; set;}
public IDataStorage SecondStorage {get; set;}
}
If I was registering these "handlers" (deriving from BaseMessageHandler) manually, I would specify a service override, indicating which component I want for properties "FirstStorage" and "SecondStorage". Something like:
.Configure(x => x.DependsOn(
ServiceOverride.ForKey("FirstStorage").Eq("FirstChoice"),
ServiceOverride.ForKey("SecondStorage").Eq("SecondChoice"))
Unfortunately, this registration is done automatically by a framework (NServiceBus). I know that if I register the handlers first (before NServiceBus has a chance to do so), these registrations will stick. But rather than try to guess and mimick the registration NServiceBus does, I wonder if I can specify service overrides in a custom IContributeComponentModelConstruction.
It seems a good place to do so, and I'm able to find these properties:
public class DataStorageOverrideContributor : IContributeComponentModelConstruction
{
public void ProcessModel(Castle.MicroKernel.IKernel kernel, Castle.Core.ComponentModel model)
{
var dataStorageDependencies = model.Properties.Where(
x => x.Dependency.TargetItemType == typeof(IDataStorage));
foreach (var propertyDependency in dataStorageDependencies)
{
// now what??
but I'm not sure the proper way to:
check if a service override is already specified (in which case I would do nothing)
add a service override to a property dependency.
Is this something that could be done inspecting and working the ComponentModel in the IContributeComponentModelConstruction.ProcessModel method?
I would use a subdependency resolver in your scenario. You can see the code below on how to use it.
Goodluck,
Marwijn.
public interface IDataStorage
{
}
public class DataStore1 : IDataStorage
{
}
public class DataStore2 : IDataStorage
{
}
public class BaseMessageHandler
{
public IDataStorage FirstStorage { get; set; }
public IDataStorage SecondStorage { get; set; }
}
public class SubDependencyResolver : ISubDependencyResolver
{
private readonly IKernel _kernel;
public SubDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model,
DependencyModel dependency)
{
return model.Implementation == typeof (BaseMessageHandler) && dependency.TargetType == typeof(IDataStorage);
}
public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model,
DependencyModel dependency)
{
var handlers = _kernel.GetHandlers(dependency.TargetType);
switch (dependency.DependencyKey)
{
case "FirstStorage":
return handlers.Single(h => h.ComponentModel.Implementation == typeof (DataStore1)).Resolve(context);
case "SecondStorage":
return handlers.Single(h => h.ComponentModel.Implementation == typeof(DataStore2)).Resolve(context);
}
return null;
}
}
[TestFixture]
public class Tests
{
[Test]
public void SomeTest()
{
var container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(new SubDependencyResolver(container.Kernel));
container.Register(
Component.For<IDataStorage>().Named("FirstChoice").ImplementedBy<DataStore1>(),
Component.For<IDataStorage>().Named("SecondChoice").ImplementedBy<DataStore2>(),
Component.For<BaseMessageHandler>()
);
var messageHandler = container.Resolve<BaseMessageHandler>();
Assert.AreEqual(typeof(DataStore1), messageHandler.FirstStorage.GetType());
Assert.AreEqual(typeof(DataStore2), messageHandler.SecondStorage.GetType());
}
}
alternative you may use:
case "FirstStorage":
return handlers.Single(h => h.ComponentModel.Name == "FirstChoice").Resolve(context);
case "SecondStorage":
return handlers.Single(h => h.ComponentModel.Name == "SecondChoice").Resolve(context);
to resolve on component name rather then implementation type.

Run code before class instanciation in ActionScript 3

I need to run code in a class declaration before its instanciation. This would be especially useful to automatically register classes in a factory. See:
// Main.as
public class Main extends Sprite
{
public function Main() : void
{
var o : Object = Factory.make(42);
}
}
// Factory.as
public class Factory
{
private static var _factory : Array = new Array();
public static function registerClass(id : uint, c : Class) : void
{
_factory[id] = function () : Object { return new c(); };
}
public static function make(id : uint) : Object
{
return _factory[id]();
}
}
// Foo.as
public class Foo
{
// Run this code before instanciating Foo!
Factory.registerClass(CLASS_ID, Foo);
public static const CLASS_ID : uint = 42;
}
AFAIK, the JIT machine for the ActionScript language won't let me do that since no reference to Foo is made in the Main method. The Foo class being generated, I can't (and don't want to) register the classes in Main: I'd like to register all the exported classes in a specific package (or library). Ideally, this would be done through package introspection, which doesn't exist in ActionScript 3.
Do you know any fix (or other solution) to my design issue?
I'm not 100% sure sure if this is what you're after, but have you tried using a Static Initializer?
public class Foo
{
// Static Initializer
{
Factory.registerClass(CLASS_ID, Foo);
}
public static const CLASS_ID : uint = 42;
}
http://life.neophi.com/danielr/2006/12/static_initializers_in_as3.html
You can use compiler options to include class byte code in the resulting SWF or SWC. But you have to compile with MXMLC (or COMPC for SWCs).

What is the best way to implement a singleton pattern class in Actionscript 3?

Since AS3 does not allow private constructors, it seems the only way to construct a singleton and guarantee the constructor isn't explicitly created via "new" is to pass a single parameter and check it.
I've heard two recommendations, one is to check the caller and ensure it's the static getInstance(), and the other is to have a private/internal class in the same package namespace.
The private object passed on the constructor seems preferable but it does not look like you can have a private class in the same package. Is this true? And more importantly is it the best way to implement a singleton?
A slight adaptation of enobrev's answer is to have instance as a getter. Some would say this is more elegant. Also, enobrev's answer won't enforce a Singleton if you call the constructor before calling getInstance. This may not be perfect, but I have tested this and it works. (There is definitely another good way to do this in the book "Advanced ActionScrpt3 with Design Patterns" too).
package {
public class Singleton {
private static var _instance:Singleton;
public function Singleton(enforcer:SingletonEnforcer) {
if( !enforcer)
{
throw new Error( "Singleton and can only be accessed through Singleton.getInstance()" );
}
}
public static function get instance():Singleton
{
if(!Singleton._instance)
{
Singleton._instance = new Singleton(new SingletonEnforcer());
}
return Singleton._instance;
}
}
}
class SingletonEnforcer{}
I've been using this for some time, which I believe I originally got from wikipedia of all places.
package {
public final class Singleton {
private static var instance:Singleton = new Singleton();
public function Singleton() {
if( Singleton.instance ) {
throw new Error( "Singleton and can only be accessed through Singleton.getInstance()" );
}
}
public static function getInstance():Singleton {
return Singleton.instance;
}
}
}
Here's an interesting summary of the problem, which leads to a similar solution.
You can get a private class like so:
package some.pack
{
public class Foo
{
public Foo(f : CheckFoo)
{
if (f == null) throw new Exception(...);
}
}
static private inst : Foo;
static public getInstance() : Foo
{
if (inst == null)
inst = new Foo(new CheckFoo());
return inst;
}
}
class CheckFoo
{
}
The pattern which is used by Cairngorm (which may not be the best) is to throw a runtime exception in the constructor if the constructor is being called a second time. For Example:
public class Foo {
private static var instance : Foo;
public Foo() {
if( instance != null ) {
throw new Exception ("Singleton constructor called");
}
instance = this;
}
public static getInstance() : Foo {
if( instance == null ) {
instance = new Foo();
}
return instance;
}
}