I have a web page where a user can drag and drop certain widgets into a single placeholder. Each widget has its own set of properties.
For example, suppose I have the following HTML widgets:
Widget1:
- Title field
- Technical name field
And another widget that is more dynamic:
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)
Now with the click of a button these settings are saved to the database. But at some point I also need to read that data from it again.
For example, suppose I have the following classes for the Widgets:
interface IWidget { }
class Widget1 : IWidget
{
public string Title {get;set;}
public string TechnicalName {get;set;}
}
class Widget2 : IWidget
{
public List<int> PickerValues {get;set;}
}
Then store that in a List
.
var widgets = new List<IWidget>();
widgets.Add(new Widget1());
widgets.Add(new Widget2());
That would work. But then getting an object from that list again is a problem:
var widget = widgets.First();
widget.????? // <-- NO INTELLISENSE!
That means it doesn't know what actual implementation it has. I'd have to cast it. But how, if I don't know what widgets are stored in there? It can be a list of 1, 5 or even 10 different widgets in any order.
How can I solve this problem?
答案 0 :(得分:1)
您目前有一个对象列表,这些对象都实现了IWidget
接口。直接访问它们只会让你对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();
答案 1 :(得分: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.
答案 2 :(得分: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
}