Архитектура плагинов с интерфейсами;Проверка интерфейса не работает
-
13-09-2019 - |
Вопрос
Я реализую простую архитектуру плагина в приложении.Требования к плагину определяются с помощью интерфейса (IPlugin), который находится в *.dll, на который ссылаются приложение и плагин.В приложении есть менеджер плагинов (также в той же *.dll), который загружает плагины, просматривая все *.dll в папке плагинов, загружает их, а затем проверяет, реализует ли плагин интерфейс.Я выполнил эту проверку двумя разными способами [ранее с помощью простого if (плагин — IPlugin)], но ни один из них не распознал, когда плагин реализует интерфейс.Вот код:
Assembly pluginAssembly = Assembly.LoadFrom(currFile.FullName);
if (pluginAssembly != null)
{
foreach (Type currType in pluginAssembly.GetTypes())
{
if (currType.GetInterfaces().Contains(typeof(IPlugin)))
{
// Code here is never executing
// even when the currType derives from IPlugin
}
}
}
Раньше я тестировал определенное имя класса («Плагин»), но затем позволял ему циклически перебирать все классы в сборке, но безрезультатно.(Это следует за примером, который я нашел в другом месте.) Чтобы сделать это немного более сложным, есть два интерфейса, каждый из которых реализует исходный интерфейс (iplugina, ipluginb).Плагин фактически реализует один из более специфических интерфейсов (IPluginB).Однако я попробовал это с плагином, просто реализующим более общий интерфейс (IPlugin), и это все равно не работает.
[Редактировать:В ответ на два ответа, которые я впервые получил] Да, я попытался использовать Isassignable от.См. следующее:
Assembly pluginAssembly = Assembly.LoadFrom(currFile.FullName);
if (pluginAssembly != null)
{
foreach (Type currType in pluginAssembly.GetTypes())
{
if (typeof(IPlugin).IsAssignableFrom(currType))
{
string test = "test";
}
}
}
Решение
Попытался ли ты:
typeof(IPlugin).IsAssignableFrom(currType)
Кроме того, типы осуществлять интерфейсы, но они не вывести от них.А BaseType
собственность и IsSubclassOf
метод показывает вывод, где IsAssignableFrom
показывает происхождение или реализацию.
Редактировать: ваши сборки подписаны?Они могут загружаться параллельные версии вашей сборки, и с тех пор Type
объекты сравниваются с ReferenceEquals
, один и тот же тип в двух параллельных сборках будет полностью независимым.
Редактировать 2: Попробуй это:
public Type[] LoadPluginsInAssembly(Assembly otherAssembly)
{
List<Type> pluginTypes = new List<Type>();
foreach (Type type in otherAssembly.GetTypes())
{
// This is just a diagnostic. IsAssignableFrom is what you'll use once
// you find the problem.
Type otherInterfaceType =
type.GetInterfaces()
.Where(interfaceType => interfaceType.Name.Equals(typeof(IPlugin).Name, StringComparison.Ordinal)).FirstOrDefault();
if (otherInterfaceType != null)
{
if (otherInterfaceType == typeof(IPlugin))
{
pluginTypes.Add(type);
}
else
{
Console.WriteLine("Duplicate IPlugin types found:");
Console.WriteLine(" " + typeof(IPlugin).AssemblyQualifiedName);
Console.WriteLine(" " + otherInterfaceType.AssemblyQualifiedName);
}
}
}
if (pluginTypes.Count == 0)
return Type.EmptyTypes;
return pluginTypes.ToArray();
}
Другие советы
Метод IsAssignableFrom — это то, что вы ищете:
Type intType = typeof(IInterface);
foreach (Type t in pluginAssembly.GetTypes())
{
if (intType.IsAssignableFrom(t))
{
}
}