расширение класса репозитория по умолчанию

#c# #.net #entity-framework

#c# #.net #entity-framework

Вопрос:

Я использую шаблон репозитория с интерфейсами, и я использую structuremap для сопоставления между ними.

В моем global.asax я определил:

     ObjectFactory.Initialize(x =>
        {
            x.For<IUnitOfWorkFactory>().Use<EFUnitOfWorkFactory>();
            x.For(typeof(IRepository<>)).Use(typeof(EFRepository<>)
        }
    );
  

Теперь я хочу добавить другой метод db к сущности MyEntity. Итак, я создал MyEntityRepository:

 class MyEntityRepository:EFRepository<MyEntity>, IMyEntityRepository {
    public void CloseCall(long callId) {
        ....
        ....
    }
}
  

Но теперь я вынужден добавить новую строку для инициализации structuremap. У меня много подобных случаев, и количество строк при инициализации structuremap становится все больше и больше.

Кроме того, в большинстве случаев добавляется только один метод, но для добавления этого единственного метода требуется интерфейс для нового репозитория, реализация в новом файле и другая инициализация structuremap — много работы для одного метода.

Как я могу это решить?

Я делаю что-то не так?

Может быть, лучше использовать метод расширения для репозитория (если есть такое расширение для generic ..)?

Комментарии:

1. Будет x.For(typeof(IRepository<>)).Use(typeof(EFRepository<>) скомпилирован?

2. @Bala R: Да, я уже запускаю приложение с ним.

Ответ №1:

Если у вас есть специальные интерфейсы, которые должны быть разрешены с помощью специального типа, вы всегда должны где-то написать код для инициализации этого. Если вы не хотите писать слишком много кода при инициализации вашей StructureMap, используйте абстрактный фабричный шаблон для вашего уровня DAL:

Заводской интерфейс:

 public interface IDalFactory
{
    IXXXRepository XXXRepository { get; }
    IYYYRepository YYYRepository { get; }
} 
  

Реализация:

 public class DalFactory : IDalFactory
{
    private IXXXRepository _xxxRepository;
    public IXXXRepository XXXRepository
    {
        return _xxxRepository ?? (_xxxRepository = new XXXRepository());
    }

    private IYYYRepository _yyyRepository;
    public IYYYRepository YYYRepository
    {
        return _yyyRepository ?? (_yyyRepository = new YYYRepository());
    }
}
  

И вы инициализируете свой IoC:

 ObjectFactory.Initialize(x =>
        {
            x.For<IUnitOfWorkFactory>().Use<EFUnitOfWorkFactory>();
            x.For<IDalFactory>().Use<DalFactory>();
        }
    );
  

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

Комментарии:

1. Я ищу способ, которым я могу добавлять новые методы в базовый репозиторий без необходимости добавлять 2 новых файла и другого редактирования файла. Я ищу более простой шаблон проектирования для расширения базового репозитория и даже иногда переопределяю его методы.

2. @Naor: Вы ищете шаблон декоратора, но все равно вам нужно написать новый класс и новый интерфейс.

Ответ №2:

На моем бизнес-уровне, где я определил созданный мной интерфейс IRepository:

 public abstract class BaseRepository<T> : IRepository<T> where T : IDataEntity
{
    protected IRepository<T> Repository { get; set; }

    public BaseRepository()
    {
        Repository = ObjectFactory.GetInstance<IRepository<T>>();
    }

    public virtual IQueryable<T> GetQuery()
    {
        return Repository.GetQuery();
    }

    public virtual IQueryable<T> GetQuery(params Expression<Func<T, object>>[] includes)
    {
        return Repository.GetQuery(includes);
    }

    public virtual void Insert(T entity)
    {
        Repository.Insert(entity);
    }

    public virtual void Update(T entity)
    {
        Repository.Update(entity);
    }

    public virtual void Delete(T entity)
    {
        Repository.Delete(entity);
    }

    public virtual void Attach(T entity)
    {
        Repository.Attach(entity);
    }
}
  

В global.asax я должен сопоставить IRepository с реализацией entity framework.
И теперь для каждого класса, который я хочу предоставить в Интернете, я должен определить:

 public class MyEntityRepository: BaseRepository<MyEntity> {
    ....
    Common queries for this entity
    ....
    ....
    overrides of insert, delete and so on
}
  

Теперь я вообще не могу использовать BaseRepository в веб-приложении, но использую репозиторий, который принадлежит сущности. Мне также не нужно регистрировать каждое расширение репозитория в structuremap. Единственное, что я должен помнить, это не использовать напрямую EFRepository (я могу получить его с помощью карты структуры — и я должен избегать его использования).