Custom construction with open generics in StructureMap
I have a typical repository interface, IRepository<T>
, and lots of concrete repositories. Most of the concrete repositories look like this:
class ConcreteRepository<T> : IRepository<T> { .. }
These are easy to register with StructureMap:
For(typeof(IRepository<>)).Use(typeof(ConcreteRepository<>));
However, a select few of my concrete repositories look l开发者_开发问答ike this:
class AbnormalRepository<T1, T2> : IRepository<T1>, IAbnormal<T2> { .. }
I still want to use these abnormal repositories as IRepository<T>
s, so for these I'm currently using special rules:
// this sucks!
For(typeof(IRepository<Foo1>)).Use(typeof(AbnormalRepository<Foo1, Bar1>));
For(typeof(IRepository<Foo2>)).Use(typeof(AbnormalRepository<Foo2, Bar2>));
It would be nice if I could just specify a function that StructureMap could use to construct my repositories, since I know that all of my abnormal repositories implement IAbnormal<T>
. Any ideas?
Create a custom IRegistrationConvention and call it from within the Scan() method of your container configuration.
You can see an example of this discussed on another stackoverflow question:
StructureMap IRegistrationConvention to register non default naming convention?
You can also see a number of IRegistrationConvention examples within the StructureMap source code itself.
I'm not following your use case all the way, but you can use a function (lambda actually) to construct your object. Use either of the two overloads:
// lambda with no params
For<IRepository<Foo1>>().Use(() => { ... });
// context is a StructureMap SessionContext
For<IRepository<Foo1>>().Use(context => { ... });
To see what is available off SessionContext, check out http://structuremap.github.com/structuremap/UsingSessionContext.htm
ADDED:
using System;
using NUnit.Framework;
using StructureMap;
namespace SMTest2
{
public interface IRepository<T> {}
public class AbnormalRepository<T,T2> : IRepository<T>{ }
[TestFixture]
public class TestOpenGeneric
{
private IContainer _container ;
[SetUp]
public void DescribeContainer()
{
_container = new Container(cfg =>
cfg.For(typeof (IRepository<>)).Use(ctx => new AbnormalRepository<String, int>()));
}
[Test]
public void TestItWorks()
{
var stringVector = _container.GetInstance(typeof (IRepository<>));
Assert.IsInstanceOf<AbnormalRepository<String,int>>(stringVector);
}
}
}
精彩评论