定义每个子类定义一次的静态属性的最佳方式是什么

本文关键字:定义 静态 属性 最佳 是什么 方式 一次 子类 | 更新日期: 2023-09-27 18:24:05

我编写了以下控制台应用程序来测试静态属性:

using System;
namespace StaticPropertyTest
{
    public abstract class BaseClass
    {
        public static int MyProperty { get; set; }
    }
    public class DerivedAlpha : BaseClass
    {
    }
    public class DerivedBeta : BaseClass
    {
    }
    class Program
    {
        static void Main(string[] args)
        {
            DerivedBeta.MyProperty = 7;
            Console.WriteLine(DerivedAlpha.MyProperty); // outputs 7
        }
    }
}

正如这个控制台应用程序所展示的,对于BaseClass的所有实例,MyProperty属性都存在一次。是否有一种模式可以让我定义一个静态属性,该属性将为每个子类类型分配存储?

给定上面的示例,我希望DerivedAlpha的所有实例共享相同的静态属性,并且DerivedBeta的所有实例都共享静态属性的另一个实例。

我为什么要这么做

我正在惰性地初始化一组具有某些属性的类属性名称(通过反射)。每个派生类实例的属性名称都是相同的,因此将其存储在每个类实例中似乎是浪费。我不能在基类中使它成为静态的,因为不同的子类将具有不同的属性。

我不想复制在每个派生类中填充集合(通过反射)的代码。我知道一种可能的解决方案是定义方法来填充基类中的集合,并从每个派生类中调用它,但这不是最优雅的解决方案。

更新-我正在做的事情的示例

应Jon的要求,下面是我尝试做的一个例子。基本上,我可以选择用[SalesRelationship(SalesRelationshipRule.DoNotInclude)]属性装饰类中的属性(还有其他属性,这只是一个简化的例子)。

public class BaseEntity
{
    // I want this property to be static but exist once per derived class.
    public List<string> PropertiesWithDoNotInclude { get; set; }
    public BaseEntity()
    {
        // Code here will populate PropertiesWithDoNotInclude with
        // all properties in class marked with
        // SalesRelationshipRule.DoNotInclude.
        //
        // I want this code to populate this property to run once per
        // derived class type, and be stored statically but per class type.
    }
}
public class FooEntity : BaseEntity
{
   [SalesRelationship(SalesRelationshipRule.DoNotInclude)]
   public int? Property_A { get; set; }
   public int? Property_B { get; set; }
   [SalesRelationship(SalesRelationshipRule.DoNotInclude)]
   public int? Property_C { get; set; }
}
public class BarEntity : BaseEntity
{
   public int? Property_D { get; set; }
   [SalesRelationship(SalesRelationshipRule.DoNotInclude)]
   public int? Property_E { get; set; }
   public int? Property_F { get; set; }
}

期望的最终结果

访问FooEntity.PropertiesWithDoNotInclude返回的List<string>为:

{
  "Property_A",
  "Property_C"
}

访问BarEntity.PropertiesWithDoNotInclude返回的List<string>为:

{
  "Property_E"
}

定义每个子类定义一次的静态属性的最佳方式是什么

两种可能的方法:

  • 使用属性;用一个属性装饰每个子类,例如

    [MyProperty(5)]
    public class DerivedAlpha
    {
    }
    [MyProperty(10)]
    public class DerivedBeta
    {
    }
    

    当然,只有当它们实际上是常量时,这才有效。

  • 使用字典:

    var properties = new Dictionary<Type, int>
    {
        { typeof(DerivedAlpha), 5) },
        { typeof(DerivedBeta), 10) },
    };
    

编辑:现在我们有了更多的上下文,本的答案非常好,使用了C#中泛型的工作方式。这就像字典的例子,但懒惰、线程安全和简单的全局访问都是内置的。

Jon像往常一样有一个很好的解决方案,尽管我不知道好的属性在这里有什么作用,因为它们必须显式添加到每个子类型中,而且它们的行为不像属性。

Dictionary方法肯定可行。这里有另一种方法,它明确声明BaseEntity的每个子类将有一个变量:

class FilteredProperties<T> where T : BaseEntity
{
     static public List<string> Values { get; private set; }
     // or static public readonly List<string> Values = new List<string>();
     static FilteredProperties()
     {
         // logic to populate the list goes here
     }
}

这样做的缺点是很难与GetType()调用配对,例如您可能在BaseEntity的方法中使用的调用。实现惰性填充的Dictionary或其包装器更适合这种用途。