0

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

这是代码

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基类。我想这可能是更好的设计,但我也很想知道我是否可以让它按原样工作。

4

2 回答 2

4

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

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

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

于 2013-06-24T17:25:19.260 回答
3

(按要求在评论中发布。感谢您的等待)

看一下SelectLINQ 查询的部分:

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

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

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

这将确保 Activator 创建前面找到的类型的实例Where

正如 Lee 还提到的,在搜索子类时,在表达式中使用类似IsSubclassOfor的东西比直接使用更可取。根据我的经验,它们的工作原理大致相同,除了也可以使用接口。IsAssignableFromWhere==IsAssignableFrom

于 2013-06-24T19:04:21.577 回答