简体   繁体   English

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

[英]Custom construction with open generics in StructureMap

I have a typical repository interface, IRepository<T> , and lots of concrete repositories. 我有一个典型的存储库接口IRepository<T> ,还有许多具体的存储库。 Most of the concrete repositories look like this: 大多数具体的存储库如下所示:

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

These are easy to register with StructureMap: 这些很容易在StructureMap中注册:

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

However, a select few of my concrete repositories look like 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: 我仍然想将这些异常存储库用作IRepository<T> ,因此对于这些,我目前正在使用特殊规则:

// 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> . 如果我仅指定一个结构映射可用于构造我的存储库的函数,那将是很好的,因为我知道我所有的异常存储库都实现了IAbnormal<T> Any ideas? 有任何想法吗?

Create a custom IRegistrationConvention and call it from within the Scan() method of your container configuration. 创建一个自定义的IRegistrationConvention并从容器配置的Scan()方法中调用它。

You can see an example of this discussed on another stackoverflow question: 您可以看到关于另一个stackoverflow问题讨论的示例:

StructureMap IRegistrationConvention to register non default naming convention? 使用StructureMap IRegistrationConvention注册非默认命名约定?

You can also see a number of IRegistrationConvention examples within the StructureMap source code itself. 您还可以在StructureMap源代码本身中看到许多IRegistrationConvention示例。

I'm not following your use case all the way, but you can use a function (lambda actually) to construct your object. 我不会一直使用您的用例,但是您可以使用一个函数(实际上是lambda)来构造您的对象。 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 要查看SessionContext可用的内容,请查看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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM