c# - 如何在不使用反射的情况下访问一系列类的公共(public)属性

标签 c# .net inheritance design-patterns reflection

我正在开发一个遗留 C# 应用程序,其中包含许多具有 5 个相同名称相同类型(字符串和整数)的公共(public)属性的业务实体类。

我需要根据 5 个通用属性在实体类上实现一些业务流程逻辑。

class A
{
    public string CommonProperty1 {get;set;}
    public int CommonProperty2 {get;set;}
    public string CommonProperty3 {get;set;}
    public string CommonProperty4 {get;set;}
    public string CommonProperty5 {get;set;}

}
class B
{
    public string CommonProperty1 {get;set;}
    public int CommonProperty2 {get;set;}
    public string CommonProperty3 {get;set;}
    public string CommonProperty4 {get;set;}
    public string CommonProperty5 {get;set;}

}
class C
{
    public string CommonProperty1 {get;set;}
    public int CommonProperty2 {get;set;}
    public string CommonProperty3 {get;set;}
    public string CommonProperty4 {get;set;}
    public string CommonProperty5 {get;set;}

}
// there more of such business classes

public static BusinessHelpr
{
   public static DoSomethingOnClassAorBorC(object theRefrence)
   {
       theRefrence.CommonProperty4 = "result of some complex calculation";
       theRefrence.CommonProperty2 = 56; // result of some complex calculation;
       theRefrence.CommonProperty5 = "result of some complex calculation";
   }

}

如果这是一个未开发的应用程序,我将从一个包含 5 个属性的基类继承,并很好地实现所需的逻辑

但是,我们决定不对业务实体进行任何重构或更改。他们不能被触摸。

因此,在我的帮助程序类中,我需要找到一种方法来获取对对象类型的引用,并通过字符串中的名称访问其属性。 这里一个明显的选择是反射。这意味着我得到一个类型,使用反射按字符串中的名称访问它的属性。 但是,我了解到在这种情况下使用反射会带来性能损失,这不是一个好的做法。

请注意,我简化了实际场景以专注于要点。所以创建下面的方法将不起作用:

static DoSomethingOnClassAorBorC(string CommonProperty1, int CommonProperty2, string CommonProperty3,string CommonProperty4, string CommonProperty5)

除了反射(reflection),我还有哪些其他选择?

最佳答案

选项1

我知道您说过您不想对模型进行任何更改,但您没有提到的一个选项是使用接口(interface)。

interface ICommon
{
    string CommonProperty1 {get;set;}
    int CommonProperty2 {get;set;}
    string CommonProperty3 {get;set;}
    string CommonProperty4 {get;set;}
    string CommonProperty5 {get;set;}
}

class A : ICommon
{
    public string CommonProperty1 {get;set;}
    public int CommonProperty2 {get;set;}
    public string CommonProperty3 {get;set;}
    public string CommonProperty4 {get;set;}
    public string CommonProperty5 {get;set;}
}
class B : ICommon
{
    public string CommonProperty1 {get;set;}
    public int CommonProperty2 {get;set;}
    public string CommonProperty3 {get;set;}
    public string CommonProperty4 {get;set;}
    public string CommonProperty5 {get;set;}
}
class C : ICommon
{
    public string CommonProperty1 {get;set;}
    public int CommonProperty2 {get;set;}
    public string CommonProperty3 {get;set;}
    public string CommonProperty4 {get;set;}
    public string CommonProperty5 {get;set;}
}

然后你就可以使用:

static DoSomethingOnClassAorBorC(ICommon common)
{
    // implementation
}

并且您的任何实体都将“正常工作”。

除了向每个实体添加 : Interface 外,您实际上不需要对实体进行任何更改,这比使用继承的侵入性更小。

选项 2

如果您真的不想对您的模型进行任何更改并且不想招致巨大的性能损失(Reflection 和dynamic 都很昂贵) , 唯一的其他选择是使用 adapter pattern在您的每个模型上。

interface ICommon
{
    string CommonProperty1 {get;set;}
    int CommonProperty2 {get;set;}
    string CommonProperty3 {get;set;}
    string CommonProperty4 {get;set;}
    string CommonProperty5 {get;set;}
}

为您的每个实体创建一个适配器类。

class AAdapter : ICommon
{
    private readonly A inner;

    public AAdapter(A inner)
    {
        if (inner == null)
            throw new ArgumentNullException(nameof(inner));
        this.inner = inner;
    }

    public string CommonProperty1 
    {
        get { return inner.CommonProperty1; }
        set { inner.CommonProperty1 = value; }
    }
    public int CommonProperty2
    {
        get { return inner.CommonProperty2; }
        set { inner.CommonProperty2 = value; }
    }
    public string CommonProperty3 
    {
        get { return inner.CommonProperty3; }
        set { inner.CommonProperty3 = value; }
    }
    public string CommonProperty4 
    {
        get { return inner.CommonProperty4; }
        set { inner.CommonProperty4 = value; }
    }
    public string CommonProperty5
    {
        get { return inner.CommonProperty5; }
        set { inner.CommonProperty5 = value; }
    }   
}

class BAdapter : ICommon
{
    private readonly B inner;

    public BAdapter(B inner)
    {
        if (inner == null)
            throw new ArgumentNullException(nameof(inner));
        this.inner = inner;
    }

    public string CommonProperty1 
    {
        get { return inner.CommonProperty1; }
        set { inner.CommonProperty1 = value; }
    }
    public int CommonProperty2
    {
        get { return inner.CommonProperty2; }
        set { inner.CommonProperty2 = value; }
    }
    public string CommonProperty3 
    {
        get { return inner.CommonProperty3; }
        set { inner.CommonProperty3 = value; }
    }
    public string CommonProperty4 
    {
        get { return inner.CommonProperty4; }
        set { inner.CommonProperty4 = value; }
    }
    public string CommonProperty5
    {
        get { return inner.CommonProperty5; }
        set { inner.CommonProperty5 = value; }
    }   
}

// Other similar adapters...

以与选项 1 相同的方式声明方法:

static DoSomethingOnClassAorBorC(ICommon common)
{
    // implementation
}

并包装您的实体类以使用它们。

DoSomethingOnClassAorBorC(new AAdapter(a));
DoSomethingOnClassAorBorC(new BAdapter(b));
DoSomethingOnClassAorBorC(new CAdapter(c));

关于c# - 如何在不使用反射的情况下访问一系列类的公共(public)属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48589416/

相关文章:

c# - 两个日期之间的房间可用性(初学者)

C# 随机生成

c# - 我如何在 linq 中对非字符串字段使用过滤器?

c# - 指定 WPF 图表的最小和最大轴

c++ - 正确的 C++ 方法来存储多类型数据

JavaScript 继承与 Array 对象(需要解释才能理解)

c# - 从 IClientMessageInspector 登录时屏蔽敏感信息

c# - 哪个更适合多核硬件?多线程或异步方法

c# - 在 C# 中删除文本文件的第一行

c++ - 错误:在C++中没有用于调用构造函数的匹配函数