方法来处理属性相同但对象类型不同的对象

本文关键字:对象 类型 属性 方法 处理 | 更新日期: 2023-09-27 18:27:19

我有大量自动生成的对象。尽管它们都是不同的、不相关的类,但所有对象都共享一些基本属性(名称、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;
}

尽管这自然是行不通的。

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

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

方法来处理属性相同但对象类型不同的对象

我可以保证遇到的所有对象都将具有被操纵的的公共属性

如果是这种情况,您可以使用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设备。您只需要让所有的数据对象类实现一个单独的接口,然后就可以处理它了。比摆弄反射简单得多,也不容易出错。

事实上,很多对象都有共同的属性,但不共享相同的祖先,至少在一个共同的界面上,这表明你的设计有问题。请重新思考。

实现这一点的多种方法,最简单的可能是创建Interface并在那里声明通用方法,让您的对象实现它,然后更改"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<IEntity> entities = new List<IEntity>();
    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);