2009-04-29 3 views
5

пыльник упрощена версия кода у меня есть:Generic проблемы фабрики класса

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>, который является общим интерфейсом. Я не могу предоставить T, потому что в случае Bool это будет bool, а в случае String это будет строка.

Любая идея, что мне нужно сделать, чтобы она работала?

ответ

5

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

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

UPDATE

Если я missunterstood вас, и вы не хотите, не универсальный интерфейс, вам придется сделать метод 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
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; 
} 

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

IControl<bool> boolControl = GetControl<bool>(); 
+3

@ Vadim - Я настоятельно рекомендую вам использовать решение Daniel, где он сравнивает типы, а не использует строки. Использование имени типа более подвержено ошибкам. –

+0

@Jon B: вы правы; сравнение типов обеспечит более надежный код. Я просто обновил оригинальный код Вадима для работы. Подход Даниила - лучший способ пойти. –

0

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

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

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

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

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

в течение определенного

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

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

Смежные вопросы