使用反射来实例化类

时间:2013-06-24 16:28:08

标签: c# reflection

我正在尝试搜索特定的命名空间并返回实现指定接口并具有指定基类的所有类的实例。

这是代码

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;
}

我遇到的问题是Assert失败,因为我找回了DrawableGameComponent的列表,不能将其视为IResettable,因此代码var r = example as IResettable始终返回null。

其他信息

我还应该提到DrawableGameComponent没有实现IResettable接口。我尝试获取的三个示例类都有DrawableGameComponent作为基类,它们还实现了IResettable

其他想法

我想也许我应该创建一个名为Example的新抽象类来实现DrawableGameComponentIResettable然后我的具体示例类可以实现Example基础类。我想这个可能是更好的设计,但我也有兴趣知道我是否可以按原样运行它。

2 个答案:

答案 0 :(得分:4)

您将错误的类型传递给Activator.CreateInstance,您应将其更改为:

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

您可能还想在Where子句中使用Type.IsSubclassOf,而不是直接查看基类。

答案 1 :(得分:3)

(根据评论要求发帖。感谢等待)

查看LINQ查询的Select部分:

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

typeof(T)传递到Activator.CreateInstance会创建一个T类型的新对象。由于您实际上想要从找到的类型中创建对象,因此您需要将其更改为:

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

这将确保Activator创建上一个Where中找到的类型的实例。

Lee还提到,在搜索子类时,在IsSubclassOf表达式中使用IsAssignableFromWhere等内容比直接==更可取。根据我的经验,他们的工作方式基本相同,除了IsAssignableFrom也适用于接口。