Используя отражение, чтобы получить все классы определенного базового типа в dll - PullRequest
18 голосов
/ 28 июля 2010

У меня есть 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;
      }
    }
  }
}

У меня 2 проблемы. Первая проблема заключается в том, что строка «if (type is CommandBase») выдает следующее предупреждение:

Данное выражение никогда не относится к указанному типу CommandBase.

Вторая проблема заключается в том, что я не могу понять, как получить экземпляр реального объекта (CommandA, CommandB и т. Д.), Просто преобразования его в CommandBase недостаточно.

Ответы [ 4 ]

30 голосов
/ 28 июля 2010

Это метод, который я использую для загрузки на основе интерфейса.

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

Конечно, ее необходимо немного изменить, чтобы она указывала на загружаемую ссылку.

7 голосов
/ 28 июля 2010

Изменить type is CommandBase на typeof(CommandBase).IsAssignableFrom(type)

7 голосов
/ 28 июля 2010

Вы должны изменить

if(type is CommandBase) 

на

if(type.IsSubclassOf(typeof(CommandBase)))

Если IsSubclassOf является обратным IsAssignableFrom.То есть, если t1.IsSubclassOf (t2) имеет значение true, то t2.IsAssignableFrom (t1) также имеет значение true.

2 голосов
/ 28 июля 2010

Это потому, что ваша type переменная Type, а не CommandBase.

Вы хотите

if(type == typeof(CommandBase))

(Спасибо, Грег, за исправление)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...