[英]How do I cast an object to its own type?
我已經閱讀了幾個關於這個問題的帖子,但沒有一個答案似乎適合我。 這是情況 - 我有一個通用函數來調用另一個類:
public class Dispatcher<T> where T : Event {
public void Notify<X>(X tEvent) where X : Event {
if (someField is IListener<X, T>) {
//this never executes--X is Event regardless of its derived type
}
}
}
和調用代碼:
public class Effect {
public Event myEvent;
public CallNotify() {
Dispatcher.Notify(myEvent);
}
}
問題是Event有幾十個派生類型,我需要將Notify()調用與派生類型一起發生為X.到目前為止,它只調用Notify <Event>(),無論我傳入什么類型的事件。編譯的唯一解決方案是調用Notify(myEvent作為DerivedEvent),但必須對每種類型進行硬編碼 - 這是不可接受的。
如果我從派生類的實例中給它一個“this”指針,那么類似的函數會正確推斷。
當然,這里有一個使用Reflection的解決方案。
你有兩個問題。
首先,你的泛型正在泄漏。 每當您需要確定特定實例的類型時,您的函數就不再是通用的。 考慮您的設計存在缺陷,並重新檢查您要做的事情。
其次, IListener<X,Y>
不是一種類型。 泛型在.NET中不通用; 運行時確定應用程序將需要的所有實際類型並創建它們。 例如,如果您在應用程序中實際使用了IListener<int,string>
,那么它將創建一個類型IListener<int,string>
。
var foo = new List<int>();
var bar = foo.GetType() == typeof(List<>);
在這個考試中, bar
是false
。
即使有這一切,是的,這是可能的。 您只需要了解泛型類型定義的反射是如何工作的。 這是MSDN上一個非常好的鏈接,解釋了它的工作原理。
我強烈建議你以這種方式重新考慮使用泛型。 有時抽象廣告荒謬不是最好的事情......
為了像你期望的那樣調用它,你必須使用反射來生成myEvent的實際類型的方法。 但我要強調的是,執行以下操作是一個不好的想法,可能意味着您的設計需要重新考慮。
MethodInfo openGenericMethod = OtherClass.GetType().GetMethod("Notify");
MethodInfo closedGenericMethod = openGenericMethod.MakeGenericMethod(myEvent.GetType());
closedGenericMethod.Invoke(OtherClass, new object[]{ myEvent });,
我實際上沒有測試上面的代碼,但它看起來像那樣
你可以放棄約束並檢查以確保它派生自Event
,如下所示:
public class Dispatcher<T> where T : Event {
public void Notify<X>(X tEvent) {
if(typeof(tEvent).IsSubclassOf(typeof(Event))
{
if (someField is IListener<X, T>) {
//this never executes--X is Event regardless of its derived type
}
}
}
}
所以我似乎已經找到了另一端的解決方法。 代替
public class Dispatcher<T> where T : Event {
public void Notify<X>(X tEvent) where X : Event {
foreach (Object l in listeners) {
if (l is IListener<X, T>) { //never true
(l as IListener<X, T>).OnEvent();
}
}
}
}
我有這個混蛋:
public class Dispatcher<T> where T : Event {
public void Notify<X>(X tEvent) where X : Event {
foreach (Object l in listeners) {
foreach (Type t in l.GetType().GetInterfaces()) {
Type[] temp = t.GetGenericArguments();
if (temp.Count() > 0 && temp[0] == tEvent.GetType()) {
MethodInfo mi = t.GetMethod("OnEvent", new Type[] {tEvent.GetType()});
mi.Invoke(l, new object[] { tEvent });
}
}
}
}
}
這似乎工作,雖然我不喜歡測試每個接口(Windows窗體至少有10個接口)。 我將嘗試使用BrandonAGr的解決方案
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.