C# 使用反射获取dll中特定基类型的所有类

C# 使用反射获取dll中特定基类型的所有类,c#,reflection,C#,Reflection,我有一个dll,它包含许多类,这些类都继承自CommandBase类。我正在尝试获取所有这些类CommandA、CommandB、CommandC等的实例。。。在C语言中使用反射,这样我就可以对每个方法调用特定的方法。以下是我到目前为止的情况: //get assemblies in directory. string folder = Path.Combine(HttpContext.Current.Server.MapPath("~/"), "bin"); var files = Direc

我有一个dll,它包含许多类,这些类都继承自CommandBase类。我正在尝试获取所有这些类CommandA、CommandB、CommandC等的实例。。。在C语言中使用反射,这样我就可以对每个方法调用特定的方法。以下是我到目前为止的情况:

//get assemblies in directory.
string folder = Path.Combine(HttpContext.Current.Server.MapPath("~/"), "bin");
var files = Directory.GetFiles(folder, "*.dll");
//load each assembly.
foreach (string file in files)
{
  var assembly = Assembly.LoadFile(file);
  if (assembly.FullName == "MyCommandProject")
  {
    foreach (var type in assembly.GetTypes())
    {
      if (!type.IsClass || type.IsNotPublic) continue;
      if(type is CommandBase)
      {
        var command = Activator.CreateInstance(type) as CommandBase;
      }
    }
  }
}
我有两个问题。第一个问题是iftype is CommandBase行发出以下警告:

给定的表达式决不是提供的CommandBase类型

第二个问题是,我不知道如何获取实际对象CommandA、CommandB等的实例,仅将其转换为CommandBase是不够的。

这是因为您的类型变量是类型,而不是CommandBase

你想要

if(type == typeof(CommandBase))
感谢Greg的更正

将CommandBase类型更改为CommandBase类型。IsAssignableFromtype

您必须更改

if(type is CommandBase) 


如果IsSubclassOf与IsAssignableFrom相反。也就是说,如果t1.IsSubclassOft2为真,那么t2.IsAssignableFromt1也为真。

这是我用于基于接口加载的方法

private static List<T> GetInstances<T>()
{
        return (from t in Assembly.GetExecutingAssembly().GetTypes()
                where t.GetInterfaces().Contains(typeof (T)) && t.GetConstructor(Type.EmptyTypes) != null
                select (T) Activator.CreateInstance(t)).ToList();
}
这是一个基于基类的函数

private static IList<T> GetInstances<T>()
{
        return (from t in Assembly.GetExecutingAssembly().GetTypes()
                       where t.BaseType == (typeof(T)) && t.GetConstructor(Type.EmptyTypes) != null
                       select (T)Activator.CreateInstance(t)).ToList();
}

当然,它需要稍微修改,以指向您正在加载的引用。

它最终是==而不是is,但是是的,这很有效,谢谢。关于我的第二期有什么建议吗?我可以告诉你,它被铸造为CommandBase,因为,好吧,你铸造它给一个,但不幸的是,我不知道如何将它铸造给更高的等级,因为你在这一点上正在失去类型安全性。通常情况下,您希望有一个可以在所有派生类中调用相同函数的接口。我怀疑它是否能够编译,因为Is需要类名,而不是类型。修复了答案中的Is->==问题。您的最后一行没有正确创建实例?使用Activator.CreateInstance,您应该拥有CommandA、CommandB。。。类根据类型,否?Activation.CreateInstance返回类型object。是,但它返回您提供的类型的对象。您可以将其存储在对象变量或CommandBase变量中,它仍然是CommandA、CommandB等实例。您可以稍后将其转换为真实类型。我没有Visual Studio要检查,但我不知道问题出在哪里。也许我知道你想要什么,但这是不可能的。我认为您希望var的类型是CommandA、CommandB等。但是var只是一种简化的表示法,它不是一种变化的类型,在编译时,它将被一个静态类型替换,在您的情况下,它将始终是CommandBase。但这只是您实例的一个容器。正如我前面所说的,里面的对象是CommandA,CommandB类型的。。。这只是因为它存储在一个更通用的变量中,所以您无法访问每个特定于对象的成员。仅适用于从父代继承的成员。也就是说,除了我的答案,从一开始就是正确的。:,但是我给你一个+1,因为我从来没有注意到IsSubclassOf方法,因为我只是使用IsAssignableFrom。+1我在键入时没有看到你的结果,但是这个msdn显示IsSubclassOf是否与IsAssignableFrom相反。也就是说,如果t1.IsSubclassOft2为真,那么t2.IsAssignableFromt1也为真。所以我们都是对的,我指的是is和==answers的答案。谢谢,但出于某种原因,它只返回CommandBase类,而不是从它继承的类。另外,如果我像GetInstances一样调用它,那么它会给我一个CommandBase对象列表,而不是我需要的对象——CommandA、CommandB等等。。听起来我需要使用接口来实现这一点。为您添加了第二个用于CommandBase类的函数。您应该检索从CommandBase继承的类的实例列表。当我把它放到一个简单的代码段测试中时,它就起作用了。我最终切换到使用接口,并使用了您的第一个代码示例,谢谢!
private static IList<T> GetInstances<T>()
{
        return (from t in Assembly.GetExecutingAssembly().GetTypes()
                       where t.BaseType == (typeof(T)) && t.GetConstructor(Type.EmptyTypes) != null
                       select (T)Activator.CreateInstance(t)).ToList();
}