[英]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
的新抽象類,該類實現DrawableGameComponent
和IResettable
,然后我的具體示例類可以僅實現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
表達式中使用IsSubclassOf
或IsAssignableFrom
類的方法比直接使用==
更可取。 根據我的經驗,它們的工作原理IsAssignableFrom
,只是IsAssignableFrom
也可以與接口一起工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.