簡體   English   中英

C#,反射,繼承和靜態字段?

[英]C#, reflection, inheritence and static fields?

我有一個從抽象超類繼承的類系列,該類由兩個具體的類實現:

public abstract class AbstractFoo 
{
    protected static string fooName = "Reset me!";

    public static string GetName()
    {
         return fooName;
    }
}

然后將子類構造為

public class BarFoo : AbstractFoo 
{
    static BarFoo() 
    {
         fooName = "Pretty Name For BarFoo";
    }
}

等等。

我想獲得所有AbstractFoo實現的漂亮名稱的列表,以便用戶可以決定使用哪個實現。

我的反射代碼看起來像

 Type fooType = typeof(AbstractFoo);

 List<Assembly> assemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());

 IEnumerable<Type> allTypes = assemblies.SelectMany<Assembly, Type>(s => s.GetTypes());
 IEnumerable<Type> fooTypes = allTypes.Where(p => p.IsSubclassOf (fooType));

 foreach (Type thisType in fooTypes) 
 {
      MethodInfo method = thisType.GetMethod ("GetName", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
      string name = (string) method.Invoke (null, null);
  // add to the list, anyhow names.Add (name);  
  }

我最后使用method.Invoke總是返回“重命名我”而不是單個名稱。

我很確定自己在這里做些愚蠢的事情,但是我不太確定該做什么。

你有兩個問題。

首先,您的靜態字段實際上不會做您想要做的事情。 AbstractFoo一個靜態字段-沒有單獨的BarFoo.fooName靜態字段。 因此,如果您有一堆子類,則最后一個子類進行類型初始化的情況都會在設置字段時“獲勝”。

接下來,當您調用BarFoo.GetName實際上僅是對AbstractFoo.GetName的調用BarFoo不會被初始化,因此您不會看到設置了“漂亮名稱”。

從根本上講,我建議您重新設計代碼。 我建議您使用屬性裝飾每個類。 這樣一來,您根本就不會依賴於類型初始值設定項,也不需要為每種類型聲明單獨的靜態成員。 唯一的缺點是該值必須為常數。

另一種選擇是使用虛擬屬性,然后將其覆蓋子類中-盡管當然需要您創建每種類型的實例。

靜態成員有一個副本。 在當前設置下,每個子類都將覆蓋該副本,從而僅提供一個名稱。 您需要在每個子類上創建一個靜態GetName函數,然后直接返回名稱。 我會推薦一些類似的東西:

public abstract class AbstractFoo
{
}

public class BarFoo : AbstractFoo 
{
    public static string GetName()
    {
        return "Pretty Name For BarFoo";
    }
}

 Type fooType = typeof(AbstractFoo);
 List<Assembly> assemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());
 IEnumerable<Type> allTypes = assemblies.SelectMany<Assembly, Type>(s => s.GetTypes());
 IEnumerable<Type> fooTypes = allTypes.Where(p => p.IsSubclassOf (fooType));
 foreach (Type thisType in fooTypes) 
 {

      MethodInfo method = thisType.GetMethod ("GetName", BindingFlags.Public | BindingFlags.Static);
      string name = (string) method.Invoke (null, null);
  // add to the list, anyhow names.Add (name);  
  }

另一種方法是將Dictionary保留為AbstractFoo的靜態成員,並讓子類的靜態初始值設定項向該Dictionary添加一些內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM