我有一些课程,我无法改变.他们有一个Prop3共同的属性:
public class c1
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public string Prop3 { get; set; }
}
public class c2
{
public string Prop2 { get; set; }
public string Prop3 { get; set; }
}
public class c3
{
public string Prop5 { get; set; }
public string Prop3 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我想在不知道类型的情况下访问此属性.我想过使用一个接口:
public interface ic
{
string Prop3 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但是此代码抛出了无效的强制转换异常:
c1 c1o = new c1() { Prop3 = "test" };
string res = ((ic)c1o).Prop3;
Run Code Online (Sandbox Code Playgroud)
Jcl*_*Jcl 11
C#不支持编译时鸭子输入,所以如果你不能改变你的类型,那就没有运气了.
你可以使用dynamic它来访问你的属性,它允许运行时鸭子输入(但是没有编译时间检查,如果使用Visual Studio,你将失去智能感知):
c1 c1o = new c1() { Prop3 = "test" };
string res = ((dynamic)c1o).Prop3;
Run Code Online (Sandbox Code Playgroud)
或通过反思:
c1 c1o = new c1() { Prop3 = "test" };
string res = (string)c1o.GetType().GetProperty("Prop3").GetValue(c1o);
Run Code Online (Sandbox Code Playgroud)
由于没有编译时检查,因此如果传递没有的实例,则需要处理异常Prop3.
或者,如果类型未密封,您可以尝试实现自己的派生类型,您可以在其中指定接口:
public interface ic
{
string Prop3 { get; set; }
}
public class c1d : c1, ic {}
public class c2d : c2, ic {}
public class c3d : c3, ic {}
Run Code Online (Sandbox Code Playgroud)
这就需要你控制实例的创建不过,情况将需要类型的c1d,c2d,c3d,将无法正常工作,如果你得到类型的对象c1,c2或c3
您可以像@David指出的那样进行显式类型转换(这是一个聪明的技巧),但这意味着您将拥有对象的两个实例.对于像问题中提到的那样非常简单的情况,它可能会...如果您需要更高级的东西,那可能会非常棘手
使用类似适配器的结构来封装转换逻辑.当然,这样做的缺点是你必须在c4弹出时修改类.
public class Adapter {
public Adapter(object c) {
if (!(c is c1 || c is c2 || c is c3))
throw new NotSupportedException();
_c = c;
}
private readonly object _c;
public string Prop3 {
get {
if (_c is c1) return ((c1)_c).Prop3;
if (_c is c2) return ((c2)_c).Prop3;
if (_c is c3) return ((c3)_c).Prop3;
throw new NotSupportedException();
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var c1o = new c1() { Prop3 = "test" };
var adapter1 = new Adapter(c1);
var res1 = adapter1.Prop3;
var c2o = new c2() { Prop3 = "test" };
var adapter2 = new Adapter(c2);
var res2 = adapter2.Prop3;
Run Code Online (Sandbox Code Playgroud)