C# 在实现具有对象类型属性的接口的类中更改属性类型
我正在编写一个TemplateEngine,它允许我在基于文本的文件中使用自己的标记。随着应用程序的成熟,我想添加控件作为插件。目前,我的结构如下所示: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
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设计工具洗脑了,这些工具大多不喜欢带有泛型类型参数的控件。;-)我想到了仿制药,但被管理层拒绝了。对于不熟悉库的详细信息的开发人员来说,这并不容易。。。(我刚刚收到一张支票)回顾过去的这几年