在StructureMap中使用开放式泛型进行自定义构造

时间:2010-09-21 02:23:15

标签: c# generics structuremap

我有一个典型的存储库接口IRepository<T>和许多具体的存储库。大多数具体的存储库看起来像这样:

class ConcreteRepository<T> : IRepository<T> { .. }

这些很容易注册到StructureMap:

For(typeof(IRepository<>)).Use(typeof(ConcreteRepository<>));

但是,我选择的几个具体的存储库看起来像这样:

class AbnormalRepository<T1, T2> : IRepository<T1>, IAbnormal<T2> { .. }

我仍然希望将这些异常存储库用作IRepository<T> s,因此对于这些我目前正在使用特殊规则:

// this sucks!
For(typeof(IRepository<Foo1>)).Use(typeof(AbnormalRepository<Foo1, Bar1>));
For(typeof(IRepository<Foo2>)).Use(typeof(AbnormalRepository<Foo2, Bar2>));

如果我能指定一个StructureMap可用于构建我的存储库的函数,那将是很好的,因为我知道我的所有异常存储库都实现了IAbnormal<T>。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

创建自定义IRegistrationConvention并从容器配置的Scan()方法中调用它。

您可以在另一个stackoverflow问题上看到这个讨论的示例:

StructureMap IRegistrationConvention to register non default naming convention?

您还可以在StructureMap源代码本身中看到许多IRegistrationConvention示例。

答案 1 :(得分:1)

我没有一直关注你的用例,但是你可以使用一个函数(实际上是lambda)来构造你的对象。使用两个重载中的任何一个:

// lambda with no params
For<IRepository<Foo1>>().Use(() => { ... });
// context is a StructureMap SessionContext
For<IRepository<Foo1>>().Use(context => { ... }); 

要查看SessionContext之外的内容,请查看http://structuremap.github.com/structuremap/UsingSessionContext.htm

<强>增加:

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);
        }
    }
}