什么是确定其定义一次每个子类的静态属性的最佳方法是什么?子类、静态、属性、定义

2023-09-04 00:43:44 作者:痴心不改将以情葬海

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

 使用系统;

命名空间StaticPropertyTest
{
    公共抽象类的BaseClass
    {
        公共静态myProperty的INT {获得;组; }
    }

    公共类DerivedAlpha:BaseClass的
    {
    }

    公共类DerivedBeta:BaseClass的
    {
    }

    类节目
    {
        静态无效的主要(字串[] args)
        {
            DerivedBeta.MyProperty = 7;
            Console.WriteLine(DerivedAlpha.MyProperty); //输出7
        }
    }
}
 

由于这个控制台应用程序演示中, myProperty的属性存在一次的BaseClass的所有实例。有没有一种模式来使用这将让我确定这将对每个子类类型分配存储的静态属性?

鉴于上面的例子中,我想 DerivedAlpha 的所有实例都共享相同的静态属性,而 DerivedBeta 来分享的另一个的静态属性的实例。

为什么我要做这个?

我懒洋洋地初始化具有特定属性的类属性名的集合(通过反射)。属性名称将是相同的每个派生类的实例,因此它似乎浪费这些信息存储在每个类的实例。我不能使它在基类静态的,因为不同的子类将具有不同的特性。

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

更新 - 对我在做什么实例

在乔恩的要求,这里有什么,我试图做一个例子。基本上,我可以选择在我的班级与 [SalesRelationship(SalesRelationshipRule.DoNotInclude)] 属性修饰属性(还有其他的属性,这只是一个简单的例子)。

 公共类BaseEntity
{
    //我想这个属性是静态的,但存在的每一次派生类。
    公开名单<字符串> PropertiesWithDoNotInclude {获得;组; }

    公共BaseEntity()
    {
        // code,这里将填充PropertiesWithDoNotInclude与
        //类的所有属性标记
        // SalesRelationshipRule.DoNotInclude。
        //
        //我想这code来填充这个属性运行一次,每
        //派生类类型,静态,但每类类型存储。
    }
}

公共类FooEntity:BaseEntity
{
   [SalesRelationship(SalesRelationshipRule.DoNotInclude)
   公众诠释? Property_A {获得;组; }

   公众诠释? Property_B {获得;组; }

   [SalesRelationship(SalesRelationshipRule.DoNotInclude)
   公众诠释? Property_C {获得;组; }
}

公共类BarEntity:BaseEntity
{
   公众诠释? Property_D {获得;组; }

   [SalesRelationship(SalesRelationshipRule.DoNotInclude)
   公众诠释? Property_E {获得;组; }

   公众诠释? Property_F {获得;组; }
}
 

期望的最终结果

访问 FooEntity.PropertiesWithDoNotInclude 返回名单,其中,串> 的:

  {
  Property_A
  Property_C
}
 
多态,父类引用接收子类对象调用方法, 属性封装,方法多态

访问 BarEntity.PropertiesWithDoNotInclude 返回名单,其中,串> 的:

  {
  Property_E
}
 

解决方案

乔恩有一个很好的解决方案像往常一样,虽然我看不出有什么好属性在这里做的,因为他们必须要明确地添加到每个亚型和他们不T像属性。

词典办法绝对可以正常工作。这里是另一种方式来做到这一点,其中明确宣布,将有每个子类一个变量 BaseEntity

 类FilteredProperties< T>其中T:BaseEntity
{
     静态公开名单<字符串>值{获得;私定; }
     //或静态公共只读目录<字符串>值=新的名单,其中,串>();
     静态FilteredProperties()
     {
         //逻辑来填充这样的例子不胜枚举这里
     }
}
 

这样做的缺点是,它是相当困难的配对与的GetType()调用,如你可能会在 BaseEntity 。 A 词典,或包装其它实现了懒惰的人口,对于那些使用比较好。

I wrote the following console app to test static properties:

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
        }
    }
}

As this console app demonstrates, the MyProperty property exists once for all instances of BaseClass. Is there a pattern to use which would allow me to define a static property which will have allocated storage for each sub-class type?

Given the above example, I would like all instances of DerivedAlpha to share the same static property, and all instances of DerivedBeta to share another instance of the static property.

Why am I trying to do this?

I am lazily initializing a collection of class property names with certain attributes (via reflection). The property names will be identical for each derived class instance, so it seems wasteful to store this in each class instance. I can't make it static in the base class, because different sub-classes will have different properties.

I don't want to replicate the code which populates the collection (via reflection) in each derived class. I know that one possible solution is to define the method to populate the collection in the base class, and call it from each derived class, but this is not the most elegant solution.

Update - Example of what I'm doing

At Jon's request, here's an example of what I'm trying to do. Basically, I can optionally decorate properties in my classes with the [SalesRelationship(SalesRelationshipRule.DoNotInclude)] attribute (there are other attributes, this is just a simplified example).

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; }
}

Desired end result

Accessing FooEntity.PropertiesWithDoNotInclude returns a List<string> of:

{
  "Property_A",
  "Property_C"
}

Accessing BarEntity.PropertiesWithDoNotInclude returns a List<string> of:

{
  "Property_E"
}

解决方案

Jon has a good solution as usual, although I don't see what good attributes do here, since they have to be explicitly added to every subtype and they don't act like properties.

The Dictionary approach can definitely work. Here's another way to do that, which explicitly declares that there will be one variable per subclass of 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
     }
}

The drawback of this is that it's rather difficult to pair with a GetType() call such as you might use in methods of BaseEntity. A Dictionary, or wrapper thereto which implements lazy population, is better for that usage.