[英]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.