Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当一个类型需要额外属性时尝试实现多态性_C#_Asp.net_.net_Polymorphism - Fatal编程技术网

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不是控件列表,它模拟了下拉列表的
项集合。由于创建的控件类型是可变的,如果是下拉列表,我需要进行额外的处理以获取列表项。同意,在下拉列表的情况下,当他需要更多的基本类型接口时,实际上没有什么可以做的。