StructureMap 3 получить запрошенный тип

У меня есть следующие регистрации StructureMap, которые работают в версии 2.6.4, и я наконец обновляюсь до последней версии SM (3.1.2 на момент написания статьи). И нужно обновить его, так как кажется, что IContext.BuildStack больше не существует.

Вот старая рабочая версия с 2.6.4:

        initialization.For(typeof(IRepository<,>))
                             .Use(context =>
                             {
                                 var genericArgs = context.BuildStack.Current.RequestedType.GetGenericArguments();

                                 return RepositoryFactory.GetInstance(genericArgs[0], genericArgs[1], repositoryName);
                             }
            );

Поэтому я подумал, что изменение его на это будет работать:

        initialization.For(typeof (IRepository<,>))
            .Use("IRepository<,>", context =>
                                   {
                                       var genericArgs = context.ParentType.GetGenericArguments();

                                       return RepositoryFactory.GetInstance(genericArgs[0], genericArgs[1],
                                           repositoryName);
                                   }
            );

Но context.ParentType имеет значение null. Когда я смотрю на context.RootType, он устанавливается в System.Object, что явно не то, что я хочу.

Мой тестовый код для получения экземпляра этого хранилища:

var userRepository = ObjectFactory.GetInstance<IRepository<User, Guid>>();

Я не вижу другой собственности, которая имеет эту информацию, но я предполагаю, что что-то упустил.

2 ответа

Решение

Вы не пропустили что-то. На GitHub кто-то разместил похожий вопрос: https://github.com/structuremap/structuremap/issues/288. Джереми Миллер, автор структурной карты, ответил:

Это должно быть новое развитие. Это должно будет прийти в версии 3.2.

Предлагаемый обходной путь - создать пользовательский экземпляр и переопределить метод ClosingType. Вы можете сделать это следующим образом:

public class CustomInstance : Instance
{
    public override IDependencySource ToDependencySource(Type pluginType)
    {
        throw new NotImplementedException();
    }

    public override Instance CloseType(Type[] types)
    {
        var repository = RepositoryFactory.GetInstance(types[0], types[1], repositoryName);                                                           
        return new ObjectInstance(repository);
    }

    public override string Description
    {
        get { throw new NotImplementedException(); }
    }

    public override Type ReturnedType
    {
        get { return typeof (IRepository<,>); }
    }
}

Теперь вам нужно только подключить открытый универсальный тип к закрывающему типу следующим образом:

initialization.For(typeof (IRepository<,>)).Use(new CustomInstance());

Я добавил новый пример в кодовую базу StructureMap 3 для этого сценария на основе вашего вопроса:

https://github.com/structuremap/structuremap/blob/master/src/StructureMap.Testing/Acceptance/builder_for_open_generic_type.cs

Я должен спросить, хотя, какова цель чего-то вроде RepositoryBuilder если вы используете контейнер IoC?

В любом случае, эта реализация должна быть более эффективной, чем старый подход с интенсивным отражением.

Другие вопросы по тегам