C# 当一个类型需要额外属性时尝试实现多态性
我有两个接口:C# 当一个类型需要额外属性时尝试实现多态性,c#,asp.net,.net,polymorphism,C#,Asp.net,.net,Polymorphism,我有两个接口: interface IDynamicControl { string Id { get; set; } string Label { get; set; } string Value { get; set; } } interface IDynamicList : IDynamicControl { IList ListItems { get; set; } } 我有一个ControlResolver类,返回IDynamicControl——出
interface IDynamicControl
{
string Id { get; set; }
string Label { get; set; }
string Value { get; set; }
}
interface IDynamicList : IDynamicControl
{
IList ListItems { get; set; }
}
我有一个ControlResolver
类,返回IDynamicControl
——出于我的目的,我有ASP.NET文本框、复选框和下拉列表的包装类,它们实现了IDynamicControl(下拉实现了IDynamicList)。要点是我可以给解析器一个控件的名称,例如“Textbox”,它会给我返回一个修改过的ASP.NET Textbox的IDynamicControl
这很好用,但问题是DropDownList。也许我有一个大脑屁,但我遇到的问题是,当控件是下拉列表时,我必须对idynamicslist进行显式转换(因为解析器返回idynamicscontrol),这样我就可以将项目添加到其中以供显示。这通常不会是一个问题,但动态控件的目的是我可以在外部存储字段类型并将其读入,因此我必须执行以下操作:
string controlType = SomeService.GetControlType();
if (controlType == "dropdown")
{
var control = (IDynamicList)ControlResolver.ResolveControl(controlType);
// set up list items
}
else
{
var control = ControlResolver.ResolveControl(controlType);
// stuff with normal controls
}
但这似乎相当丑陋。我可以在基中包含ListItems属性,在不使用它的类中抛出NotImplemented,但这违反了ISP,甚至比if语句更难闻。简而言之,我希望我的解析器返回一种类型的控件,这样我就不需要使用不同的Resolve()方法,但在使用代码时,如果且仅当控件是下拉列表时,我必须做额外的工作
除非我弄错了,或者我忘记了一些基本的东西,否则有更好的解决方案吗?或者我应该使用if语句吗?我不能使用基类,因为我的所有“动态”类都继承自基本ASP.NET UI类。一个方法不能返回不同的类型,除非它是非泛型的。在您的情况下,您无法传递泛型类型参数,因此无论如何都必须应用某种显式强制转换。此外,由于您有不同的设置逻辑,您还必须应用一些条件检查 您可以摆脱的一件事是有条件的
if
检查(想象一下10种类型的控件需要多少if
yu),您可以使用IDictionary
作为初始化函数的缓存,这样代码就会非常干净:
IDictionary<string, Func<IDynamicControl>> setupWorkerProvider
这是应该的。您的ResolveControl方法提供了一个合同保证,它将返回一个IDynamicControl。它不能保证它将返回任何比这更具体的内容 想象一下,如果您有以下代码:
public Object foo(int x) {
if (x%2 == 0) {
return new String("Hello");
} else {
return new Integer(1);
}
}
您希望调用者拥有所有的字符串方法和所有的整数方法吗?我认为将原始代码重构为更干净的代码的最简单方法如下:
var control = ControlResolver.ResolveControl(controlType);
// ... do common logic for all controls
var list = control as IDynamicList;
if (list != null)
{
// .. do additional logic for list controls
}
调用ControlResolver.ResolveControl
的代码实际上不必知道“下拉”控件的任何特殊规则。它真正需要知道的是解析控件是否实现了idynamicslist
接口
当然,您仍然需要一些条件逻辑,但至少这些条件是基于代码已经知道的已知接口,而不是底层实现细节
当然,您可以采取其他方法来进一步进行抽象,但这似乎是一个可以在不影响任何其他代码的情况下进行的小更改。我建议,既然您知道您想要一个IDynamicList,那么您就有一个解析器方法(ListControlResolver?)返回一个。也许它只是调用您现有的解析器并在返回之前将其强制转换,但作为调用方的您并不关心这一点。见鬼,这可能有利于以后管理其他列表y控件。为什么不使用IList ListItems?因为DynamicList不是控件列表,它模拟了下拉列表的
项集合。由于创建的控件类型是可变的,如果是下拉列表,我需要进行额外的处理以获取列表项。同意,在下拉列表的情况下,当他需要更多的基本类型接口时,实际上没有什么可以做的。