Как хранить методы с возвращаемым типом c в коллекции? - PullRequest
1 голос
/ 17 января 2020

Итак, моя цель - создать класс (ProviderManager), который вы можете попросить вернуть объект по типу, например так:

var a = ProviderManager.GetObject<ObjA>();

ProviderManager содержит словарь, который отображает типы для делегатов, этих делегатов. являются классами, которые создают объекты конкретного типа (Provider>. Когда вызывается GetObject, ProviderManager вызывает функцию, которая создает конкретный объект. Поставщики реализуются в отдельном проекте.

Provider Manager

public class ProviderManager
{
    private readonly Dictionary<Type, Action> _ProviderMapping = new Dictionary<Type, Action>();

    public void Register<T>(Type objType, IProvider<T> provider)
    {
        _ProviderMapping.Add(objType, provider.GetObject());
    }

    public T GetObject<T>()
    {
        _ProviderMapping.FirstOrDefault(t => t.Key == typeof(T)).Value();
    }
}

Интерфейс провайдера

public interface IProvider<T>
{
    void Register();
    T GetObject();
}

Пример провайдера

public class ProviderForA : IProvider<ObjA>
{
    private ProviderManager _Manager;

    public ProviderForA(ProviderManager manager)
    {
        _Manager = manager;
    }

    public void Register()
    {
        _Manager.Register(typeof(ObjA), this);
    }

    public ObjA GetObject()
    {
        return new ObjA();
    }
}

Проблема заключается в том, что _ProviderMapping.Add (objType, provider.GetObject () ) ; вызывает ошибку «невозможно преобразовать T в Sytem.Action». Добавление функции void работает, поэтому я предполагаю, что она связана с возвращаемым значением. Я также пытался добавить универсальный c возвращаемый тип в Action, но это также не дает работа.

Цель состоит в том, чтобы проект (модуль провайдера) отвечал за создание объектов, он регистрирует класс, который реализует интерфейс провайдера. rface у менеджера провайдера (менеджерский модуль). Затем пользовательский код запрашивает у модуля менеджера объект конкретного типа. Менеджер перенаправляет вызов поставщику, который возвращает фактический объект.

1 Ответ

0 голосов
/ 17 января 2020

Вы, вероятно, хотите что-то вроде этого:

public class ProviderManager
{
    private readonly Dictionary<Type, Func<object>> _providerMapping =
        new Dictionary<Type, Func<object>>();

    public void Register<T>(IProvider<T> provider)
    {
        _providerMapping .Add(typeof(T), () => provider.GetObject());
    }

    public T GetObject<T>()
    {
        if (!_providerMapping.TryGetValue(typeof(T), out var factory))
            throw ...
        return (T)factory();
    }
}

Тогда:

public void Register()
{
    _Manager.Register(this);
}

У нас есть словарь, полный множества делегатов, которые возвращают различные типы. Мы должны использовать общий тип среди них, который равен object, и хранить Func<object> s в нашем словаре. Затем мы приводим object к соответствующему T в GetObject<T>().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...