2010-04-18 2 views
6

Я знаю, что заголовок немного запутанный, но голый со мной. (Я готов к предложениям по новому заголовку lol) Я пишу TemplateEngine, который позволит мне использовать мою собственную разметку в текстовых файлах. Я хочу добавить элементы управления в качестве плагинов по мере созревания приложения. В настоящее время у меня есть структура вроде следующего:Изменение типа свойства в классе, который реализует интерфейс с свойством типа объекта

interface IControl 
    string Id 
    object Value 

class Label : IControl 
    string Id 
    string Value 

class Repeater : IControl 
    string Id 
    List<IControl> Value 

Теперь вы увидите странную часть сразу же в классе повторителя со свойством Value. Я надеялся, что наличие типа Value в качестве объекта в интерфейсе позволит мне гибко расширять элементы управления, пока я иду. Компилятору это не нравится, и по какой-то причине я предполагаю.

Итог: я пытаюсь получить все классы управления для реализации одного и того же интерфейса, но для свойства Value имеют разные типы.

Есть ли у кого-нибудь предложения, как это сделать?

Примечание: Пожалуйста, не включайте предложения, такие как использование Spark View Engine для шаблонов. Есть причина, по которой я создаю дополнительную работу для себя.

+0

Что вы спрашиваете? – SLaks

+0

@SLaks: LOL Извините, мне может понадобиться видеоклип, объясняющий это немного лучше. пытаясь вдаваться в подробности, может возникнуть роман – used2could

+0

Я пытаюсь получить все классы управления для реализации того же интерфейса, но для свойства Value имеют разные типы. – used2could

ответ

8

Обычно Repeater будет реализовывать что-то другое, например, IItemsControl.

EDIT 1

(удалено для краткости)

EDIT 2

Ах хорошо, вы всегда можете использовать явную реализацию интерфейса, конечно:

interface IControl 
{ 
    string Id { get; set; } 
    object Value { get; set; } 
} 

class Label : IControl 
{ 
    public string Id { get; set; } 
    public string Value { get; set; } 

    object IControl.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (string)value; } 
    } 
} 

class Repeater : IControl 
{ 
    public string Id { get; set; } 
    public IList<IControl> Value { get; set; } 

    object IControl.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (IList<IControl>)value; } 
    } 
} 
+0

да это единственный другой маршрут, о котором я мог думать – used2could

+0

+1 для выяснения того, что дерьмо, о котором я даже говорил, – used2could

+0

lolz ... просто тренирую свои навыки ясновидения: > ... Я обновил свой ответ на примере. – herzmeister

1

Нет , компилятор не позволяет одинаковым полям имен отличаться t, кроме тех, которые определены в интерфейсе в производных классах.

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

Однако, если вы возвращаете значение, возвращаемое функцией, то оно работает, но вам нужно проверить тип возвращаемого значения, потому что возвращаемые типы должны соответствовать функции, иначе вы получите ошибку, что функция интерфейса не была реализована ,

interface IControl 
    { 
     object Value(); 
    } 
    class A : IControl 
    { 
     string m_value = string.Empty; 
     public object Value() { return m_value; } 
    }; 
    class B : IControl 
    { 
     List<IControl> m_value = new List<IControl>(); 
     public object Value() { return m_value; } 
    }; 
    .... 
    object o = new B().Value(); 
    if (o is List<IControl>) 
     MessageBox.Show("List"); 

[Update]
Вы должны быть осторожны, если явного определения тела свойств. Одно имя для двух свойств было бы опасным, если реализация не будет выполнена тщательно.

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

 public IList<IControl> Value 
     object IControl.Value 

Смотрите этот пример:

... 
    class Repeater : IControl 
    { 
     List<IControl> m_Value = new List<IControl>(); 
     public IList<IControl> Value 
     { 
      get { return this.m_Value; } 
      set { this.m_Value = (IList<IControl>)value; } 
     } 
     object IControl.Value 
     { 
      get 
      { 
       return this.m_Value; 
      } 
      set 
      { 
       this.m_Value = new List<IControl>(); 
       this.m_Value.Add(new Label()); 
       this.m_Value.AddRange((List<IControl>)value); 
      } 
     } 
    } 
    ... 
    Repeater b = new Repeater(); 
    IControl i = b; 
    List<IControl> list = new List<IControl>(); 
    list.Add(new Repeater()); 
    i.Value = list; 

Вы можете заметить, что список контейнеров в Repeater будет иметь разные значения, когда данные добавляются через IControl (из-за явного определения IContainer.Value).

+0

+1 Спасибо за указание на явное определение свойства. – used2could

3

вы можете также использовать дженерик:

interface IControl<T> 
{ 
    string ID{get;set;} 
    T Value{get;set;} 
} 

class SomeControl : IControl<string> 
{ 
    public string ID{get;set} 
    public string Value{get;set;} 
} 

class SomeOtherControl : IControl<int> 
{ 
    public string ID{get;set} 
    public int Value{get;set;} 
} 

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

Конечно, это не сработает, если у вас не будет доступа к источнику IControl.

Редактировать: была опечатка. Исправлено:

+0

Да, мы могли бы использовать дженерики тоже, я не думал об этом, потому что мне промывают мозги инструментами проектирования пользовательского интерфейса, которые в основном не любят элементы управления с типичными параметрами типа. ;-) – herzmeister

+0

Я думал о дженериках, и это было отклонено руководством. Что-то об этом нелегко для разработчиков, которые не знакомы с деталями библиотеки ... (я просто собираю чек) – used2could

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