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 для этого сценария на основе вашего вопроса:
Я должен спросить, хотя, какова цель чего-то вроде RepositoryBuilder
если вы используете контейнер IoC?
В любом случае, эта реализация должна быть более эффективной, чем старый подход с интенсивным отражением.