C# 在实现具有对象类型属性的接口的类中更改属性类型

C# 在实现具有对象类型属性的接口的类中更改属性类型,c#,interface,C#,Interface,我正在编写一个TemplateEngine,它允许我在基于文本的文件中使用自己的标记。随着应用程序的成熟,我想添加控件作为插件。目前,我的结构如下所示: interface IControl string Id object Value class Label : IControl string Id string Value class Repeater : IControl string Id List<IControl> Va

我正在编写一个TemplateEngine,它允许我在基于文本的文件中使用自己的标记。随着应用程序的成熟,我想添加控件作为插件。目前,我的结构如下所示:

interface IControl
    string Id
    object Value

class Label : IControl
    string Id
    string Value

class Repeater : IControl
    string Id
    List<IControl> Value
接口IControl
字符串Id
对象值
类标签:IControl
字符串Id
字符串值
类中继器:IControl
字符串Id
列表值
现在,您将立即在Repeater类中看到带有Value属性的奇怪部分。我希望在接口中使用值类型作为对象将允许我灵活地扩展控件。编译器不喜欢这样,我想这是有原因的


一句话:我试图让所有控件类实现相同的接口,但Value属性的类型不同

有人对如何做到这一点有什么建议吗


注意:请不要建议使用Spark View Engine作为模板。我为自己创建额外的工作是有原因的。

通常,
中继器会实现一些不同的功能,例如
IItemsControl

编辑1

(为简洁起见删除)

编辑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; }
    }
}
接口IControl
{
字符串Id{get;set;}
对象值{get;set;}
}
类标签:IControl
{
公共字符串Id{get;set;}
公共字符串值{get;set;}
对象IControl.Value
{
获取{返回此.Value;}
设置{this.Value=(字符串)值;}
}
}
类中继器:IControl
{
公共字符串Id{get;set;}
公共IList值{get;set;}
对象IControl.Value
{
获取{返回此.Value;}
设置{this.Value=(IList)值;}
}
}

否,编译器不允许相同名称字段具有不同的数据类型,除非在派生类的接口中定义了不同的数据类型

        public IList<IControl> Value
        object IControl.Value
属性(因为接口中不允许字段)应该在派生类中实现,并且它们需要具有相同的数据类型。因此,在没有显式声明的情况下,您可能无法对属性执行此操作

但是,如果您将值设置为由函数返回,那么它可以工作,但是您需要检查返回类型,因为返回类型应该与函数匹配,否则您将得到一个错误,即接口的函数没有实现

    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");
接口IControl
{
对象值();
}
A类:IControl
{
字符串m_值=string.Empty;
公共对象值(){return m_Value;}
};
B类:IControl
{
列表m_值=新列表();
公共对象值(){return m_Value;}
};
....
对象o=新的B().Value();
if(o是列表)
MessageBox.Show(“列表”);
[更新]
如果显式定义属性体,则必须小心。如果不小心实现,两个属性使用一个名称将是危险的

如果这两个属性包含不同的定义,那么对于接口和类的最终使用将无法解释

        public IList<IControl> Value
        object IControl.Value
公共IList值
对象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;
。。。
类中继器:IControl
{
列表m_值=新列表();
公共价值
{
获取{返回此.m_值;}
设置{this.m_Value=(IList)Value;}
}
对象IControl.Value
{
得到
{
返回此.m_值;
}
设置
{
此.m_值=新列表();
此.m_值.Add(新标签());
此.m_值.AddRange((列表)值);
}
}
}
...
中继器b=新中继器();
i控制i=b;
列表=新列表();
添加(新的中继器());
i、 值=列表;

您可以观察到,通过IControl添加数据时,Repeater中的列表容器将具有不同的值(因为IContainer.Value的显式定义)。

您还可以使用泛型:

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
{
字符串ID{get;set;}
T值{get;set;}
}
类SomeControl:IControl
{
公共字符串ID{get;set}
公共字符串值{get;set;}
}
类SomeOtherControl:IControl
{
公共字符串ID{get;set}
公共int值{get;set;}
}
如果它只是一个需要更改的返回值,那么我更喜欢它,而不是显式接口。但是,我认为如果您有几个属性,每个属性都将返回不同的类型,那么您就不会想要IControl。至少,我不会。在这种情况下,我建议使用显式接口

当然,如果您没有访问IControl源代码的权限,这将不起作用


编辑:有一个打字错误。修正了

@SLaks:LOL抱歉,我可能需要一个视频剪辑来更好地解释它。尝试深入了解更多细节可能会导致一个新问题。我正在尝试让所有控制类实现相同的接口,但Value属性的类型不同。用一个新的示例再次更新了我的答案:->是的,这是我能想到的LZ的唯一其他途径。。。只是训练我的洞察力:->。。。我用一个例子更新了我的答案。这可能并不总是有效的。如果属性的显式定义不同于本地属性,那么将是危险的。看我的例子。是的,我们也可以使用泛型,我没有考虑过,因为我被UI设计工具洗脑了,这些工具大多不喜欢带有泛型类型参数的控件。;-)我想到了仿制药,但被管理层拒绝了。对于不熟悉库的详细信息的开发人员来说,这并不容易。。。(我刚刚收到一张支票)回顾过去的这几年