StructureMap 2.6.1, IRepository <T>и EFRepository <T, TContext> - PullRequest
4 голосов
/ 10 мая 2011

Так что я подумал, что буду ловким и попробую это. Мне нужно обойти контекст, не обновляя его каждый раз, и уметь определять сопоставления (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-й, я получаю удар с

Количество предоставленных универсальных аргументов не равно арности определения общего типа. Имя параметра: экземпляр

Полагаю, это потому, что я не говорю structmap, какой тип передать в IRepository, когда я передаю 2? Как я могу это сделать? ... я могу это сделать?

1 Ответ

3 голосов
/ 10 мая 2011

Это должно быть возможно, но это действительно грязно ... если кто-то не знает лучшего способа.

Сначала вам нужно изменить способ создания 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>>();

Получит вас большую часть пути туда. Я думаю, вам все еще нужно правильно установить универсальный для второго универсального параметра targetType, прежде чем он будет работать, хотя.

...