Шаблон фильтра с универсальным TypeOf - PullRequest
0 голосов
/ 07 ноября 2018

Я реализую шаблон фильтра (критериев), и я не уверен, что лучший подход заключается в создании универсального TypeOfCriteria.

Чтобы дать некоторый контекст, часть системы фильтрации является специфической, например, у меня есть фильтр EmailAddressContains внутри папки UserCriteria. Пользовательский класс является абстрактным, и есть несколько различных пользовательских типов, унаследованных от этого базового класса, например AdminUser и FullControlUser. Другие части системы имеют похожие деревья наследования. Сначала я реализовал определенные критерии TypeOf, такие как TypeOfAdminUser, но вскоре решил, что могу сделать это более общим.

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

Подход 1

public interface ICriteria<T> where T : BaseEntity
{
    IEnumerable<T> MeetCriteria(IEnumerable<T> entities);
}

public class TypeOfCriteria<T> : ICriteria<T> where T : BaseEntity
{
    private readonly Type _type;

    public TypeOfCriteria(Type type)
    {
        _type = type;
    }

    public IEnumerable<T> MeetCriteria(IEnumerable<T> entities)
    {
        return from T entity in entities
               where entity.GetType().Equals(_type)
               select entity;
    }
}

Использование:

ICriteria<User> criteria = new TypeOfCriteria<User>(typeof(AdminUser));
admins = criteria.MeetCriteria(users);

Подход 2

public interface ICriteria<T> where T : BaseEntity
{
    IEnumerable<T> MeetCriteria(IEnumerable<T> entities);
}

public class TypeOfCriteria<T, TResult> : ICriteria<T>
    where T : BaseEntity
    where TResult : BaseEntity
{
    public IEnumerable<T> MeetCriteria(IEnumerable<T> entities)
    {
        return entities.OfType<TResult>().Cast<T>();
    }
}

Использование:

ICriteria<User> criteria = new TypeOfCriteria<User, AdminUser>();
admins = criteria.MeetCriteria(users);

Подход 3

public interface ICriteria<T> where T : BaseEntity
{
    IEnumerable<T> MeetCriteria<TResult>(IEnumerable<T> entities);
}

public class TypeOfCriteria<T> : ICriteria<T> where T : BaseEntity
{
    public IEnumerable<T> MeetCriteria<TResult>(IEnumerable<T> entities)
    {
        return entities.OfType<TResult>().Cast<T>();
    }
}

Использование:

ICriteria<User> criteria = new TypeOfCriteria<User>();
admins = criteria.MeetCriteria<AdminUser>(users);

Плюсы и минусы

Подход 1 больше всего напоминает мои другие классы Criteria, где я передаю фактические критерии в конструкторе (new EmailAddressContains (". Com")).

Реализация подхода 2 в MeetCriteria выглядит чище. Я не уверен в производительности, похоже, она может быть быстрее, но это не совсем тот показатель, о котором я беспокоюсь для этого проекта.

Мне нравится Подход 3 меньше всего, потому что он требует, чтобы я изменил интерфейс.

...