It is possible, BUT I would look for an alternative, if possible. The problem is that to work with an open generic, you must use some reflection. This means that you get a performance hit.
public class FooRegistry:Registry { public FooRegistry() { For(typeof(IFoo<>)).Use(x => { var ParamType = x.BuildStack.Current.RequestedType .GetGenericArguments()[0]; return BuildUsingFooFactory(ParamType); }); } private object BuildUsingFooFactory(Type paramType) { var factoryType = typeof (FooFactory<>).MakeGenericType(new[] {paramType}); var createMethod = factoryType.GetMethod("Create"); object factory = Activator.CreateInstance(factoryType); return createMethod.Invoke(factory, new[] {"SomeParameterString"}); } } public class FooFactory<T> { public IFoo<T> Create(string param) { return new Foo<T>(); } } public interface IFoo<T> { } public class Foo<T> : IFoo<T> { }
What you do in order is the following:
- Find out what the requested general argument is. (ParamType)
- Create a non-open generic type for factory (factoryType)
- Remove the creation method from it. (CreateMethod)
- Create a factory instance using an activator (factory)
- Call the create method on the factory instance with your some parameter.
StructureMap takes care of outputting output to the right interface.
The best decision
Instead of using IFoo directly, use IFooFactory. This makes it a lot cleaner, you have an open shared mapping with IFooFactory <>. Then just get the type of FooFactory that you need to create your objects.
public class FooRegistry:Registry { public FooRegistry() { For(typeof (IFooFactory<>)) .Use(typeof (FooFactory<>)) .CtorDependency<string>("connection") .Is("SomeConnectionString"); } } public interface IFooFactory<T> { IFoo<T> CreateInstance(); } public class FooFactory<T> : IFooFactory<T> { public FooFactory(string connection) { } public IFoo<T> CreateInstance() { return new Foo<T>(); } } public interface IFoo<T> { } public class Foo<T> : IFoo<T> { }
source share