статический константный указатель на глобальный изменчивый

ИМО как абстракция Repository, так и абстракция UnitOfWork имеют очень ценное место в любом значимом развитии. Люди будут спорить о деталях реализации, но так же, как есть много способов скинуть кошку, есть много способов реализовать абстракцию.

Ваш вопрос конкретно использовать или не использовать и почему.

Как вы, несомненно, поняли, что у вас уже есть оба шаблона, встроенные в Entity Framework, DbContext - UnitOfWork, а DbSet - Repository. Обычно вам не нужно тестировать единицы UnitOfWork или Repository, поскольку они просто облегчают между вашими классами и базовыми реализациями доступа к данным. То, что вам нужно будет делать, снова и снова, издевается над этими двумя абстракциями, когда модуль тестирует логику ваших услуг.

Вы можете высмеивать, подделывать или что угодно с внешними библиотеками, добавляя уровни зависимостей кода (которые вы не контролируете) между логикой, выполняющей тестирование, и проверяемой логикой.

So что ваша собственная абстракция для UnitOfWork и Repository дает вам максимальный контроль и гибкость при издевательском тестировании вашего устройства.

Все очень хорошо, но для меня реальная сила этих абстракций это простой способ применения методов Ориентированного программирования и придерживаться принципов SOLID.

Итак, у вас есть IRepository:

public interface IRepository
    where T : class
{
    T Add(T entity);
    void Delete(T entity);
    IQueryable AsQueryable();
}

И его реализация:

public class Repository : IRepository
    where T : class
{
    private readonly IDbSet _dbSet;
    public Repository(PPContext context) 
    {
        _dbSet = context.Set();
    }

    public T Add(T entity)
    { 
        return _dbSet.Add(entity); 
    }

    public void Delete(T entity)
    {
        _dbSet.Remove(entity); 
    }

    public IQueryable AsQueryable() 
    {
        return _dbSet.AsQueryable();
    }
}

Пока что ничего необычного, но теперь мы хотим добавить некоторые протоколы - легко с помощью журнала Decorator .

public class RepositoryLoggerDecorator : IRepository
    where T : class
{
    Logger logger = LogManager.GetCurrentClassLogger();
    private readonly IRepository _decorated;
    public RepositoryLoggerDecorator(IRepository decorated)
    {
        _decorated = decorated;
    }

    public T Add(T entity)
    {
        logger.Log(LogLevel.Debug, () => DateTime.Now.ToLongTimeString() );
        T added = _decorated.Add(entity);
        logger.Log(LogLevel.Debug, () => DateTime.Now.ToLongTimeString());
        return added;
    }

    public void Delete(T entity)
    {
        logger.Log(LogLevel.Debug, () => DateTime.Now.ToLongTimeString());
        _decorated.Delete(entity);
        logger.Log(LogLevel.Debug, () => DateTime.Now.ToLongTimeString());
    }

    public IQueryable AsQueryable()
    {
        return _decorated.AsQueryable();
    }
}

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

Теперь, много раз я видел этот вопрос в StackOverflow - «как вы заставляете Entity Framework работать в среде с несколькими арендаторами?».

https://stackoverflow.com/search?q=%5Bentity-framework%5D+multi+tenant

Если у вас есть абстракция Repository, тогда ответ «легко» добавьте декоратор "

public class RepositoryTennantFilterDecorator : IRepository
    where T : class
{
    //public for Unit Test example
    public readonly IRepository _decorated;
    public RepositoryTennantFilterDecorator(IRepository decorated)
    {
        _decorated = decorated;
    }

    public T Add(T entity)
    {
        return _decorated.Add(entity);
    }

    public void Delete(T entity)
    {
        _decorated.Delete(entity);
    }

    public IQueryable AsQueryable()
    {
        return _decorated.AsQueryable().Where(o => true);
    }
}

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

Ответ, который обычно приходит на ум, когда кто-то говорит «почему я должен иметь абстракцию (например, Repository), над той или иной сторонней библиотекой «есть», почему бы и нет? »

PS Декораторы чрезвычайно просты в применении с использованием контейнера IoC, такого как SimpleInjector .

[TestFixture]
public class IRepositoryTesting
{
    [Test]
    public void IRepository_ContainerRegisteredWithTwoDecorators_ReturnsDecoratedRepository()
    {
        Container container = new Container();
        container.RegisterLifetimeScope();
        container.RegisterOpenGeneric(
            typeof(IRepository<>), 
            typeof(Repository<>));
        container.RegisterDecorator(
            typeof(IRepository<>), 
            typeof(RepositoryLoggerDecorator<>));
        container.RegisterDecorator(
            typeof(IRepository<>), 
            typeof(RepositoryTennantFilterDecorator<>));
        container.Verify();

        using (container.BeginLifetimeScope())
        {
            var result = container.GetInstance>();

            Assert.That(
                result, 
                Is.InstanceOf(typeof(RepositoryTennantFilterDecorator)));
            Assert.That(
                (result as RepositoryTennantFilterDecorator)._decorated,
                Is.InstanceOf(typeof(RepositoryLoggerDecorator)));
        }
    }
}

1
задан Cacahuete Frito 17 January 2019 в 12:09
поделиться

1 ответ

Эта конструкция просто объявляет константный указатель на неконстантный объект. Таким образом, вам разрешено изменять ссылочный объект, но не сам указатель.

 #define flag_it_ptr flag_it_1 

выполнят работу без указателей. Я думаю, что вы усложняете простые вещи.

0
ответ дан P__J__ 17 January 2019 в 12:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: