#generics #structuremap
#дженерики #structuremap
Вопрос:
Итак, я подумал, что буду хитрым и попробую это. Мне нужно передавать контекст, не обновляя его каждый раз, И иметь возможность определять сопоставления (Entity framework) — для этого мне нужно наследовать, а затем переопределить класс DbContext. Я хотел бы сохранить его подключаемым к любому контексту, который я добавляю, так что это то, что привело меня к этому. Я получил интерфейс IRepository, который принимает (объект) с вашими обычными подозреваемыми в нем, и его реализацию с зависимостью от IContextFactory …
public interface IContextFactory<T> where T : DbContext
{
T Context { get; }
}
И в моем «EFRepository»
public class EFRepository<T, TContext> : IRepository<T> where T : class
where TContext : DbContext
{
public EFRepository(IContextFactory<TContext> contextFactory)
{
}
}
В моем отображении я выполнил одно из этих заданий…
x.For(typeof(IContextFactory<>)).Use(typeof(ContextFactory<>));
x.For(typeof(IRepository<>)).Use(typeof(EFRepository<,>));
Хорошо, круто. В своих модульных тестах я пробую это таким образом…
var repository = ObjectFactory.GetInstance<EFRepository<Currency, EFContext>>();
var repository2 = ObjectFactory.GetInstance<IRepository<Currency>>();
Первый работает, проблем нет. 2-й, я получаю удар с
Количество предоставленных универсальных аргументов не равно арности определения универсального типа. Имя параметра: создание экземпляра
Я предполагаю, что это потому, что я не указываю structuremap, какой дженерик передать в IRepository, поскольку я передаю 2? Как мне это сделать? …могу ли я это сделать?
Ответ №1:
Это должно быть возможно, но это действительно грязно … если кто-то не знает лучшего способа.
Сначала вам нужно изменить способ создания EFRepository<,>
. Используя .Use(context => ...)
перегрузку, вы можете получить доступ к контексту, подобному context.BuildStack.Current.RequestedType.GetGenericArguments()
, чтобы получить универсальный тип, к которому вы хотите получить доступ. Затем вы можете создать новый экземпляр, EFRepository<,>
используя отражение и получая IContextFactory
из контекста.
Таким образом, независимо от того, что что-то вроде
ObjectFactory.Configure(x =>
{
x.For(typeof(IContextFactory<>)).Use(typeof(ContextFactory<>));
x.For(typeof (IRepository<>)).Use(context =>
{
Type arg1 = context.BuildStack.Current.RequestedType.
GetGenericArguments()[0];
Type targetType =
typeof (EfRepository<,>).MakeGenericType(new[] {arg1, typeof (IContextFactory<>)});
return Activator.CreateInstance(targetType,
new[] {context.GetInstance(typeof (IContextFactory<>))});
});
//x.For(typeof(IRepository<>)).Use(typeof(EfRepository<,>));
});
var repository = ObjectFactory.GetInstance<EfRepository<Currency, EfContext>>();
var repository2 = ObjectFactory.GetInstance<IRepository<Currency>>();
Поможет вам пройти большую часть пути к этому. Я думаю, вам все еще нужно правильно установить generic для второго универсального параметра TargetType, прежде чем он заработает.
Комментарии:
1. итак, реальный ответ таков: «это отстой, делай это другим способом» … Я согласен с этим! Я пока оставлю вопрос открытым, но это может быть правильным ответом. И вы правы, это действительно отстой. 🙁