我有几门课我不能改。它们有一个共同的属性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; }
}现在,我想在不知道类型的情况下访问这个属性。我想使用一个接口:
public interface ic
{
string Prop3 { get; set; }
}但是,此代码引发无效的强制转换异常:
c1 c1o = new c1() { Prop3 = "test" };
string res = ((ic)c1o).Prop3;发布于 2016-08-19 12:00:19
C#不支持编译时duck-typing,所以如果您不能更改您的类型,那就没有希望了。
您可以使用dynamic访问您的属性,这允许运行时鸭子类型(但不需要编译时检查,如果使用Visual,则会失去智能感知):
c1 c1o = new c1() { Prop3 = "test" };
string res = ((dynamic)c1o).Prop3;或通过反射:
c1 c1o = new c1() { Prop3 = "test" };
string res = (string)c1o.GetType().GetProperty("Prop3").GetValue(c1o);由于没有编译时检查,所以您需要处理异常,以防您传递一个没有Prop3的实例。
如果类型未被密封,则可以尝试实现自己的派生类型,其中可以指定接口:
public interface ic
{
string Prop3 { get; set; }
}
public class c1d : c1, ic {}
public class c2d : c2, ic {}
public class c3d : c3, ic {}这将要求您控制实例的创建,但是,实例需要类型为c1d、c2d、c3d,如果您获得c1、c2或c3类型的对象,则无法工作。
正如@David所指出的那样,您可以进行显式类型转换(这是一个聪明的技巧),但这意味着您将拥有对象的两个实例。对于一个非常简单的例子,比如问题中的那个,它可能会.如果你需要更高级的东西,那可能会很棘手。
发布于 2016-08-19 12:15:04
使用类似适配器的构造来封装转换逻辑。当然,这样做的缺点是当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();
}
}
}用法:
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;发布于 2016-08-19 12:43:35
另一种方法是使用反射获取具有指定名称的属性的值。
例如,编写如下简单的助手方法:
public static T GetProperty<T>(object obj, string name)
{
return (T) obj.GetType().GetProperty(name).GetValue(obj);
}然后给出以下不相关的类:
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; }
}
public class C4
{
public string Prop4 { get; set; }
public string Prop5 { get; set; }
}您可以像这样访问Prop3属性:
object c1 = new C1 {Prop3 = "C1"};
object c2 = new C2 {Prop3 = "C2"};
object c3 = new C3 {Prop3 = "C3"};
object c4 = new C4();
Console.WriteLine(GetProperty<string>(c1, "Prop3")); //Prints C1
Console.WriteLine(GetProperty<string>(c2, "Prop3")); //Prints C2
Console.WriteLine(GetProperty<string>(c3, "Prop3")); //Prints C3
Console.WriteLine(GetProperty<string>(c4, "Prop3")); // Throws an exception.https://stackoverflow.com/questions/39038536
复制相似问题