Метод интерфейса имеет аргумент интерфейса, но хочет использовать аргумент класса в реализации - PullRequest
1 голос
/ 08 ноября 2019

У нас есть набор компонентов, и каждый из компонентов должен быть загружен по-своему.

Рассмотрим следующее:

public interface IComponent
{
    Type LoaderType {get;}
}

public class ComponentA: IComponent
{
    Type LoaderType => typeof(ComponentALoader);
}

public class ComponentB: IComponent
{
    Type LoaderType => typeof(ComponentBLoader);
}

public interface ILoader
{
    void Load(IComponent example);
}

Есть ли способ, чтобы при реализацииILoader Я могу использовать тип компонента в загрузчиках вместо интерфейса (чтобы избежать приведения)?

Пример:

public class ComponentALoader: ILoader
{
    void Load(ComponentA component) {}
}

public class ComponentBLoader: ILoader
{
    void Load(ComponentB component) {}
}

[РЕДАКТИРОВАТЬ: это текущая реализация, которая работает,но требует приведения в каждом загрузчике]:

public class ComponentALoader: ILoader
{
    void Load(IComponent component) 
    {
        // This is the cast that I was looking to avoid in favor of having the type in the method signature
        var compA = (ComponentA) component;
        doSomethingWithA();
    }
}

public class ComponentBLoader: ILoader
{
    void Load(IComponent component)
    {
        // This is the cast that I was looking to avoid in favor of having the type in the method signature
        var compB = (ComponentB) component;
        doSomethingWithB();
    }
}

public class ComponentBLoader: ILoader
{
    void Load(ComponentB component) {}
}

Точка входа выглядит примерно так:

List<IComponent> components = listOfComponents;
foreach (var component in components)
{
    // Retrieves the correct loader from a list of loaders 
    // based on the type property on the components
    var loader = getLoaderForComponent(component); 
    loader.Load(component);
}

РЕДАКТИРОВАТЬ: 1) Стоит отметить, что мы легко говорим более 100 компонентовсо связанными с ними загрузчиками, поэтому класс загрузчика с перегруженными методами для каждого компонента - это не то, к чему мы бы хотели обратиться

2) Список загрузчиков передается основному загрузчику с помощью DI, яне совсем уверен, как мы будем делать это с универсальным интерфейсом. Может быть, ILoader интерфейс для включения DI, а затем ILoader<T> с методом Load. Не уверен, как бы я сопоставил с данным ILoader вызов метода на ILoader<T>.

3) tl; dr Мы хотим избежать того, что главный загрузчик знает о многих типах компонентов и загрузчиков

4) Текущее решение работает, может быть, просто необходим литье в каждом загрузчике

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Посмотрим, насколько хорошо я понял твой вопрос. Как сказано в комментариях, чтобы избежать приведения, вы можете сделать свой интерфейс универсальным и определить в реализующих классах общий тип:

public interface IComponent
{
    Type LoaderType { get; }
}

public class ComponentA : IComponent
{
    public Type LoaderType => typeof(ComponentALoader);
}

public class ComponentB : IComponent
{
    public Type LoaderType => typeof(ComponentBLoader);
}

public interface ILoader<T> where T : IComponent // This restriction allows only types that implement the interface inside the load method
{
    void Load(T example);
}

public class ComponentALoader : ILoader<ComponentA>
{
    public void Load(ComponentA component) { }  
}

public class ComponentBLoader : ILoader<ComponentB>
{
    public void Load(ComponentB component) { }
}

Этот код компилируется, и вы можете использовать тип в методе Load вместоинтерфейса

0 голосов
/ 08 ноября 2019

Вы должны использовать универсальный класс

public class Component<T> wher T:IComponent
{
    void Load(T component) {}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...