2015-05-04 2 views
0

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

Например, предположим, что у меня есть следующие HTML-виджеты:

Widget1: 
- Title field 
- Technical name field 

И еще один виджет, который является более динамичным:

Widget2: 
- Range picker field 1 (0 to 100) 
- Range picker field 2 (0 to 100) 
       ------------------ 
       | (+) Add picker | 
       ------------------ 
(can add as many range pickers as needed) 

Теперь одним нажатием кнопки эти настройки сохраняются в база данных. Но в какой-то момент мне также нужно снова прочитать эти данные.

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

interface IWidget { } 

class Widget1 : IWidget 
{ 
    public string Title {get;set;} 
    public string TechnicalName {get;set;} 
} 

class Widget2 : IWidget 
{ 
    public List<int> PickerValues {get;set;} 
} 

Затем сохранить, что в List.

var widgets = new List<IWidget>(); 
widgets.Add(new Widget1()); 
widgets.Add(new Widget2()); 

Это сработает. Но затем получить объект из этого списка снова проблема:

var widget = widgets.First(); 
widget.????? // <-- NO INTELLISENSE! 

Это означает, что он не знает, что фактическая реализация имеет. Мне пришлось бы его бросить. Но как, если я не знаю, какие виджеты хранятся там? Это может быть список из 1, 5 или даже 10 различных виджетов в любом порядке.

Как я могу решить эту проблему?

+0

Так же, как примечание стороны: http://stackoverflow.com/questions/7552677/are-empty-interfaces-code-smell – Habib

+2

Точка создания абстракции с интерфейсом, что * вы не должны забота * о конкретной реализации. В настоящее время ваш интерфейс не имеет смысла. Что вы хотите делать с этими виджетами? –

+0

Что вы хотите сделать с IWidget, когда вы вытащите его из списка? –

ответ

1

В настоящее время у вас есть список объектов, которые реализуют интерфейс IWidget. Доступ к ним напрямую даст вам только intellisense по свойствам IWidget (у которого их нет).

Чтобы решить эту проблему, вам необходимо либо поставить некоторые свойства в интерфейсе IWidget или проверить тип каждого элемента, а затем бросить его, как:

IWidget widget = widgets.First(); 

var widget1 = widget as Widget1; 

if (widget1 != null) 
{ 
    widget1.TechnicalName = "new name"; // <-- We have intellisense 
} 

Вы также можете иметь некоторую логику, проверяет каждый виджет в цикле, как:

foreach (var widget in widgets) 
{ 
    if (widget is Widget1) 
    { 
     var widget1 = (Widget1) widget; 
     // Do something with Widget1 types here 
    } 
    else if (widget is Widget2) 
    { 
     var widget2 = (Widget2)widget; 
     // Do something with Widget2 types here 
    } 
} 

в качестве альтернативы, вы можете просто получить первый WIDGET1 (или WIDGET2) из ​​списка, делая что-то вроде:

Widget1 widget = widgets.OfType<Widget1>().First(); 
0

Может быть, ваш выбор должен проверять тип экземпляра первым:

var widget = widgets.First(); 
if (widget is Widget1) 
{ 
    var widget1 = (Widget1) widget; 
    widget1.DoSomethingSpecificToWidget1(); 
} 

В качестве альтернативы, с дополнительной функциональностью Linq, вы можете легко разделить ваш список genric подсписков. Это будет хорошо работать, если вам не нужно обрабатывать виджетов в том порядке, в котором они хранятся в переменной widgets.

var w1List = widgets.OfType<Widget1>();// you may also call `.ToList()` 
var w2List = widgets.OfType<Widget2>(); 

foreach (var w1 in w1List) 
{ 
    w1.DoSomethingSpecificToWidget1(); // w1 is now Widget1 
} 
1

Вам нужно будет использовать полиморфизм для решения вашей проблемы:

interface IWidget 
{ 
    public void readData(); 
} 

class Widget1 : IWidget 
{ 
    public string Title { get; set; } 
    public string TechnicalName { get; set; } 

    public void readData() 
    { 
     Console.WriteLine("- Title: {0}\n- Technical name: {1}", Title, TechnicalName); 
    } 
} 

class Widget2 : IWidget 
{ 
    public List<int> PickerValues { get; set; } 

    public void readData() 
    { 
     StringBuilder builder = new StringBuilder(); 
     for (int i = 1; i <= PickerValues.Count; i++) 
     { 
      builder.AppendLine(String.Format("- Range picker field {0}: {1}",i,PickerValues[i-1])); 
     } 
     Console.WriteLine(builder.ToString()); 
    } 
} 

А потом ...

 var widgets = new List<IWidget>(); 
     widgets.Add(new Widget1()); 
     widgets.Add(new Widget2()); 
     var widget = widgets.First(); 
     widget.readData(); // will print correct output for each type of widget, as implemented on each widget. 
Смежные вопросы