PragmaGames
@PragmaGames
Увлекаюсь Unity.

Как найти соответствие по generic типу?

Всем привет. Есть примерно такая структура. Нужно реализовать класс провайдер, должен быть список из процессоров, и поиск процессора по поступающему в метод apply параметру. Хотелось бы видеть "красивую" или наилучшую реализацию данного класса. Можно добавлять свои интерфейсы, или изменять имеющиеся, главное что бы сохранился основной посыл.

public interface IParam
{
}

public interface IProcessor<in T> where T : IParam
{
        public void Apply(T param);
}

public class ConcreteProcessorA : IProcessor<ConcreteParamA>

public class ConcreteParamA : IParam

public class ConcreteProcessorB : IProcessor<ConcreteParamB>

public class ConcreteParamB : IParam

public class Provider
{

     public List<IProcessor> _processors;
     
     publick void Apply(IParam)
     {
           
     }
}
  • Вопрос задан
  • 62 просмотра
Решения вопроса 2
В твоём случае - только через рефлексию брать GetType у приходящего параметра, а потом искать в списке такой класс, у которого женерик параметр имеет совместимый тип. (тоже через GetType, GetImplementingInterfaces, и GetGenericParameter).
Список соответственно придётся делать в виде List.
Чтобы каждый раз такой поиск не проводить - можно сделать Dictionary, где ключ - тип параметра, а значение - подходящий процессор.

Ещё можешь попробовать паттерн "цепочка ответственности" - тогда процессор должен принимать какой-нибудь абстрактный object и иметь метод CanApply, в котором делать проверку, соответствует ли реальный тип.
Ещё можешь посмотреть на то, как например сделан
Ответ написан
Комментировать
AshBlade
@AshBlade Куратор тега C#
Просто хочу быть счастливым
Одно из решений
public interface IParam
{
}

public interface IProcessor
{ }

public interface IProcessor<in T>: IProcessor 
    where T : IParam
{
    public void Apply(T param);
}

public class ConcreteProcessorA : IProcessor<ConcreteParamA>
{
    public void Apply(ConcreteParamA param)
    {
        Console.WriteLine("Hello from processor A");
    }
}

public class ConcreteParamA : IParam
{
    
}

public class ConcreteProcessorB : IProcessor<ConcreteParamB>
{
    public void Apply(ConcreteParamB param)
    {
        Console.WriteLine("hello form ProcessorB");
    }
}

public class ConcreteParamB : IParam
{
    
}

public class Provider
{
    public Provider(IEnumerable<IProcessor> processors)
    {
        _processors = processors.ToList();
    }
    private List<IProcessor> _processors;
     
    public void Apply<TParam>(TParam param) where TParam: IParam
    {
        foreach (var processor in _processors.Where(p => p
                                                        .GetType()
                                                        .GetInterfaces()
                                                        .Any(i => i.IsAssignableTo(typeof(IProcessor<TParam>))))
                                             .Cast<IProcessor<TParam>>())
        {
            processor.Apply(param);
        }
        throw new InvalidOperationException("Для переданного типа нет обработчика");
    }
}

public class Program
{
    static void Main(string[] args)
    {
        var provider = new Provider(new IProcessor[]
                                    {
                                        new ConcreteProcessorA()
                                    });
        
        provider.Apply(new ConcreteParamA());
        try
        {
            provider.Apply(new ConcreteParamB());
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        
    }
}

Сначала выдает
Hello from processor A
затем пишет исключение, т.к. обработчика не нашлось
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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