Пользовательская конструкция с открытыми дженериками в StructureMap - PullRequest
1 голос
/ 21 сентября 2010

У меня типичный интерфейс репозитория, 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 ]

2 голосов
/ 21 сентября 2010

Создайте пользовательское соглашение IRegistrationConvention и вызовите его из метода Scan () конфигурации вашего контейнера.

Вы можете увидеть пример этого, обсужденный на другом вопросе stackoverflow:

StructureMap IRegistrationConvention для регистрации соглашения о присвоении имен не по умолчанию?

Вы также можете увидеть несколько примеров IRegistrationConvention в самом исходном коде StructureMap.

1 голос
/ 21 сентября 2010

Я не совсем слежу за вашим вариантом использования, но вы можете использовать функцию (собственно лямбду) для создания вашего объекта. Используйте одну из двух перегрузок:

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