Таблица поиска в C # с типами и действиями - PullRequest
0 голосов
/ 22 января 2019

Я хочу изменить свои многие, если на таблицу поиска.

У меня есть типы и методы. Я хочу соединить их.

if (propertyType == typeof(bool) || propertyType == typeof(bool?))
DoBool(propertyType);

if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
DoDateTime(propertyType);

if (propertyType == typeof(Guid) || propertyType == typeof(Guid?))
DoGuid(propertyType);

Я должен создать Dictionary<Type, Action>()? Или какой лучший элегантный способ сделать это?

Можете ли вы дать мне несколько советов, с чего мне начать или где я могу найти решение?

Ответы [ 4 ]

0 голосов
/ 14 февраля 2019

Я создал свою собственную реализацию, которая немного отличается, но я использовал предложение @DaggeJ, так что спасибо!

Сначала я создал базовый класс обработчика. После этого я использовал эту базу на разных типах классов. Вы можете увидеть это ниже.

BaseClass:

public abstract class QueryHandler<T> where T : class
{
    //I added here more property. 

    public abstract Type[] Types { get; }

    protected QueryHandler(//Properties)
    {
        //Properties null check
    }

    public abstract IQueryable<T> Handle();
}

Потомок класса:

internal class GuidQuery<T> : QueryHandler<T> where T : class
{
    public override Type[] Types => new Type[] { typeof(Guid), typeof(Guid?) };

    public GuidQuery(//Properties) : base(//Properties)
    {
    }

    public override IQueryable<T> Handle()
    {
        // Implementation
    }
}

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

public IQueryable<T> GetQuery()
{
    var queryHandlerList = new List<QueryHandler<T>>()
    {
        new IntQuery<T>(//Properties),
        new DateTimeQuery<T>(//Properties),
        new StringQuery<T>(//Properties),
        new BoolQuery<T>(//Properties),
        new GuidQuery<T>(//Properties),
        new EnumQuery<T>(//Properties)
    };
}

return query = queryHandlerList.FirstOrDefault(h => GetType<T>(h, property.PropertyType)).Handle();

private bool GetType<T>(QueryHandler<T> handler, Type type) where T: class
{
    if (handler.Types.FirstOrDefault(t => t == type) == type || handler.Types.FirstOrDefault(t => t == type.BaseType) == type.BaseType) return true;

    return false;
}
0 голосов
/ 22 января 2019

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

private readonly IDictionary<Type, Action<Type>> _lookup;

, затем вы можете определить метод для инициализации _dict,

private void AddEntry<T>(Action<Type> action) where T : struct
{       
    _lookup[typeof(T)] = action;
    _lookup[typeof(Nullable<T>)] = action;
}

private void DoInt(Type type) { /* implementation */ }

AddEntry<bool>(type => { /* implementation */ });
AddEntry<int>(DoInt);
0 голосов
/ 22 января 2019

Поскольку речь идет больше об управлении потоком кода, чем о чистом поиске, я бы, вероятно, использовал бы объектно-ориентированный подход и поместил код для каждого «обработчика» в отдельные классы (с общими вещами внутри базового класса).

Вы можете создать общий интерфейс, такой как

public interface ITypeHandler {
    void HandleType(Type type);
}

... и поместить реализацию обработчиков в словарь типа Dictionary<Type, ITypeHandler>, если хотите, или у вас может быть свойствов интерфейсе, определяя, какой тип он обрабатывает, и выбирая из списка (возможно, Dependency Injected) обработчики на основе этого свойства.

Это добавляет такие преимущества, как разделение задач, тестируемость и т. д.

(Обратите внимание, что * Handler не очень хорошее имя, вам нужно будет создать лучшее имя на основе сценария, который вы описываете.)

0 голосов
/ 22 января 2019

Вы можете создать Dictionary<Type, Action<Type>>:

var dict = new Dictionary<Type, Action<Type>>() {
    {typeof(bool), DoBool},
    {typeof(bool?), DoBool},
    {typeof(DateTime), DoDateTime},
    {typeof(Datetime?), DoDateTime},
    {typeof(Guid), DoGuid},
    {typeof(Guid?), DoGuid}
};

А затем назовите это так:

dict[propertyType](propertyType)
...