Общая задача класса фабрики - PullRequest
5 голосов
/ 29 апреля 2009

Ниже приведен упрощенный вариант кода, который у меня есть:

public interface IControl<T>
{
    T Value { get; }
}

public class BoolControl : IControl<bool>
{
    public bool Value
    {
        get { return true; }
    }
}

public class StringControl : IControl<string>
{
    public string Value
    {
        get { return ""; }
    }
}
public class ControlFactory
{
    public IControl GetControl(string controlType)
    {
        switch (controlType)
        {
            case "Bool":
                return new BoolControl();
            case "String":
                return new StringControl();
        }
        return null;
    }
}

Проблема в методе GetControl класса ControlFactory. Потому что он возвращает IControl, и у меня есть только IControl , который является универсальным интерфейсом. Я не могу предоставить T, потому что в случае Bool это будет bool, а в случае String это будет строка.

Есть идеи, что мне нужно сделать, чтобы это заработало?

Ответы [ 3 ]

5 голосов
/ 29 апреля 2009

Просто выведите IControl<T> из IControl.

public interface IControl<T> : IControl
{
    T Value { get; }
}

UPDATE

Если я вас неправильно понял, и вам не нужен неуниверсальный интерфейс, вам придется также сделать метод GetControl() универсальным.

public IControl<T> GetControl<T>()
{
    if (typeof(T) == typeof(Boolean))
    {
        return new BoolControl(); // Will not compile.
    }
    else if (typeof(T) == typeof(String))
    {
        return new StringControl(); // Will not compile.
    }
    else
    {
        return null;
    }
}

Теперь у вас есть проблема, заключающаяся в том, что новые элементы управления не могут быть неявно приведены к IControl<T>, и вам придется сделать это явным.

public IControl<T> GetControl<T>()
{
    if (typeof(T) == typeof(Boolean))
    {
        return new (IControl<T>)BoolControl();
    }
    else if (typeof(T) == typeof(String))
    {
        return (IControl<T>)new StringControl();
    }
    else
    {
        return null;
    }
}

UPDATE

Изменен состав актеров с as IControl<T> на (IControl<T>). Это предпочтительнее, потому что это вызовет исключение, если есть ошибка, в то время как as IControl<T> молча возвращает null.

3 голосов
/ 29 апреля 2009
public IControl<T> GetControl<T>()
{
    switch (typeof(T).Name)
    {
        case "Bool":
            return (IControl<T>) new BoolControl();
        case "String":
            return (IControl<T>) new StringControl();
    }
    return null;
}

Обновление; исправил пару ошибок в коде. Вот звонок, чтобы получить класс:

IControl<bool> boolControl = GetControl<bool>();
0 голосов
/ 29 апреля 2009

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

Даже если бы вы могли это сделать, в чем выгода

IControl<bool> boolControl = controlFactory.GetControl("bool");

или тот, который будет работать,

IControl<bool> boolControl = controlFactory.GetControl<bool>("bool");

свыше определенного

IControl<bool> boolControl = controlFactory.GetBoolControl("bool");

В любом случае, у вас есть переключатель () на стороне клиента. Либо верните объект, либо используйте нетипизированный интерфейс IControl.

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