簡體   English   中英

使用反射實例化類

[英]Using reflection to instantiate classes

我正在嘗試搜索特定的名稱空間,並返回實現指定接口並具有指定基類的所有類的實例。

這是代碼

private List<T> GetInstancesWithInterface<T, T2>(string @namespace)
{
    var tList = Assembly.GetExecutingAssembly()
                         .GetTypes()
                         .Where(t => t.Namespace == @namespace)
                         .Where(t => t.BaseType == (typeof (T)) && t.GetInterfaces().Contains(typeof(T2)))
                         .Select(t => (T)Activator.CreateInstance(typeof(T), this))
                         .ToList();
    return tList;
}

這是調用代碼

var examples = GetInstancesWithInterface<DrawableGameComponent, IResettable>("GamePhysics.Physics");

foreach (var example in examples)
{
    Debug.Assert(example is IResettable);
    var r = example as IResettable;
    _examples.Add(r);
    Components.Add(example);
    if (Components.Count == 0) continue;
    example.Enabled = false;
    example.Visible = false;
}

我遇到的問題是斷言失敗,因為我得到了DrawableGameComponent的列表,該列表無法視為IResettable因此代碼var r = example as IResettable始終返回null。

附加信息

我還應該提到DrawableGameComponent不實現IResettable接口。 我要獲取的三個示例類都將DrawableGameComponent作為基類,並且它們還實現了IResettable

其他想法

我當時在想,也許我應該創建一個名為Example的新抽象類,該類實現DrawableGameComponentIResettable ,然后我的具體示例類可以僅實現Example基類。 我想這可能是更好的設計,但是我也很想知道是否可以按原樣工作。

您將錯誤的類型傳遞給Activator.CreateInstance ,應將其更改為:

.Select(t => (T)Activator.CreateInstance(t, this))

您可能還希望在Where子句中使用Type.IsSubclassOf ,而不是直接查看基類。

(根據評論的要求發布。感謝您的等待)

看一下LINQ查詢的Select部分:

.Select(t => (T)Activator.CreateInstance(typeof(T), this))

typeof(T)傳遞給Activator.CreateInstance將創建一個T類型的新對象。 由於您實際上是在尋找發現類型之外的對象,因此您需要將其更改為:

.Select(t => (T)Activator.CreateInstance(t, this))

這將確保激活器創建在先前的Where找到的類型的實例。

正如Lee所提到的,在搜索子類時,在Where表達式中使用IsSubclassOfIsAssignableFrom類的方法比直接使用==更可取。 根據我的經驗,它們的工作原理IsAssignableFrom ,只是IsAssignableFrom也可以與接口一起工作。

暫無
暫無

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

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