处理具有共同属性但不同对象类型的对象的方法

我有大量自动生成的对象。 虽然它们都是不同的,不相关的类,但所有对象都共享一些基本属性(名称,id等)。 我不控制这些对象的生成,所以不幸的是我无法采用实现接口的理想方法。 我想创建一个方法,在其中我传递这些对象中的任意一个并使用这些公共属性执行某些操作。

一般的想法是这样的:

someObj a = new someObj(); a.name = "sara"; diffObj b = new diffObj(); b.name = "joe"; string phrase = string.Format("I am with {0} and {1}", getName(a), getName(b)); private string getName(object anyObjWithName) { return anyObjWithName.name; } 

虽然自然这不起作用。

我认为generics方法可能会有答案,但我能看到用当前类型调用它的唯一方法是使用genericMethod.Invoke ,它仍然存在无法解析传递的对象属性的相同问题。方法。 这与调用generics方法不同,类型参数仅在执行时知道或如何使用给定的Type对象调用generics方法? 其中只有类型的类型或属性在方法中使用,而不是对象的属性。

我知道这会(非常)容易出错,但我可以保证遇到的所有对象都会被操纵共同的属性。

我可以保证遇到的所有对象都会被操纵共同的属性

如果是这种情况,您可以使用dynamic

 private string getName(dynamic anyObjWithName) { return anyObjWithName.name; } 

请注意,使用任何没有name属性的对象在运行时才会失败。

如果要添加一点安全性,可以捕获在属性不存在时抛出的RuntimeBinderException

 private string getName(dynamic anyObjWithName) { try { return anyObjWithName.name; } catch(RuntimeBinderException) { return "{unknown}"; } } 

如果您对D Stanley提到的使用动态的性能不满意,您可以随时尝试FastMember 。

在前两个代码示例中,您需要知道开始使用它的所有内容。

你正在那里创建一个Rube Goldberg设备。 您应该让所有数据对象类实现单个接口,然后您可以对此进行处理。 比摆弄reflection更简单,更容易出错。

事实上,许多对象具有共同的属性但不共享相同的祖先,至少在一个通用接口上,表明您的设计出了问题。 重新考虑一下。

实现这个的多种方法,最简单的可能是创建接口并在那里声明常用方法,让你的对象实现它,然后改变“getName”方法接受对象

 private string getName(IMyInterface anyObjWithName) { return anyObjWithName.name; } 

正确的方法是使用界面,如果您拥有您正在使用的类型

 public interface IEntity { int ID { get; set; } string Name { get; set; } } public class TypeOne : IEntity { public int ID { get; set; } public string Name { get; set } public string BespokePropertyOne { get; set;} } public class TypeTwo : IEntity { public int ID { get; set; } public string Name { get; set; } public float BespokePropertyTwo { get; set; } } static void Main(string[] args) { List entities = new List(); entities.Add(new TypeOne() { ID = 1, Name = "Bob", BespokePropertyOne = "blablabla" }); entities.Add(new TypeTwo() { ID = 2, Name = "Alice", BespokePropertyTwo = 5.4f }); foreach (IEntity entity in entities) { Console.WriteLine("ID: {0} Name: {1}", entity.ID, entity.Name); } } 

这个答案是在编辑问题之前编写的,说明在这种情况下接口是不可能的。 也许它可以帮助别人阅读这个问题。

接口:

 interface Iname { string Name { get; set; } } 

使用界面:

 class A : Iname { public string Name { get; set; } } class B : Iname { public string Name { get; set; } } 

方法:

 string GetName(Iname o) { return o.Name; } 

使用:

 A a = new A { Name = "First" }; B b = new B { Name = "Last" }; Text = GetName(a) + " " + GetName(b);