Метод вызывает исключение ReflectionTypeLoadException в Assembly.GetTypes()C#

Место общения программистов C#
Ответить
Anonymous
 Метод вызывает исключение ReflectionTypeLoadException в Assembly.GetTypes()

Сообщение Anonymous »

Поток обновлений внизу :)
Я использую архитектуру плагинов в приложении .net 8. Плагины загружаются через:
PluginLoader.cs

Код: Выделить всё

public class PluginLoader
{
private List _plugins = new List();

public PluginLoader(string[] pluginPaths)
{
_plugins = pluginPaths.SelectMany(pluginPath =>
{
Assembly pluginAssembly = LoadPlugin(pluginPath);
return CreatePlugins(pluginAssembly);
}).ToList();
}

public List GetPlugins() => _plugins;

private static Assembly LoadPlugin(string relativePath)
{
// Navigate up to the solution root
string root = Path.GetFullPath(Path.Combine(
Path.GetDirectoryName(
Path.GetDirectoryName(
Path.GetDirectoryName(
Path.GetDirectoryName(
Path.GetDirectoryName(typeof(Program).Assembly.Location)))))));

string pluginLocation = Path.GetFullPath(Path.Combine(root, relativePath.Replace('\\', Path.DirectorySeparatorChar)));

var loadContext = new PluginLoadContext(pluginLocation);
return loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(pluginLocation)));
}

private static IEnumerable CreatePlugins(Assembly assembly)
{
int count = 0;
// EXCEPTION IS HERE
foreach (Type type in assembly.GetTypes())
{
if (typeof(ILmsPlugin).IsAssignableFrom(type))
{
ILmsPlugin result = Activator.CreateInstance(type) as ILmsPlugin;
if (result != null)
{
count++;
yield return result;
}
}
}

if (count == 0)
{
string availableTypes = string.Join(",", assembly.GetTypes().Select(t => t.FullName));
throw new ApplicationException(
$"Can't find any type which implements ILmsPlugin in {assembly} from {assembly.Location}.\n" +
$"Available types: {availableTypes}");
}
}
}

Интерфейс плагинов выглядит следующим образом:
ILmsPlugin.cs
< pre class="lang-none Prettyprint-override">

Код: Выделить всё

public interface ILmsPlugin
{
public string Name { get; }

public string MachineName { get; }

public Type ConfigurationClass { get; }

public void SetConfiguration(string configuration);

public Task CreateQuiz(Quiz quiz);

public ILmsPluginInstanceConfiguration? GetConfiguration();
}
И конкретный класс:

Код: Выделить всё

public class LmsPlugin : ILmsPlugin
{
private ILmsPluginInstanceConfiguration? Configuration { get; set; }

public string Name { get => "Mock LmsPlugin"; }

public string MachineName { get => "mock_lmsplugin"; }

public Type ConfigurationClass { get => typeof(MockLmsPluginConfiguration); }

public Task  CreateQuiz(Quiz quiz)
{
ILmsPluginQuizOutputDto dto = new LmsPluginQuizOutput
{
Name = quiz.Name,
CourseId = 1
};

return Task.FromResult(dto);
}

public void SetConfiguration(string? configuration)
{
if (configuration == null)
{
return;
}

Configuration = JsonSerializer.Deserialize(configuration, ConfigurationClass) as ILmsPluginInstanceConfiguration;
}

public ILmsPluginInstanceConfiguration? GetConfiguration()
{
return Configuration;
}
}

Это ошибка:

Код: Выделить всё

System.Reflection.ReflectionTypeLoadException : Unable to load one or more of the requested types.
Method 'CreateQuiz' in type 'MockLmsPlugin.LmsPlugin' from assembly 'MockLmsPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.RuntimeModule.GetTypes()
at LmsPluginManager.PluginLoader.CreatePlugins(Assembly assembly)+MoveNext() in /Users/[removed]/Sites/[r]]/[r]]/LmsPluginManager/PluginLoader.cs:line 41
at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection)
at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.ToList()
at LmsPluginManager.PluginLoader..ctor(String[] pluginPaths) in /Users/[removed]/Sites/[r]]/[r]]/LmsPluginManager/PluginLoader.cs:line 12
at Tests.UnitTests.PluginManagerTests.PluginManagerTest.PluginIsAvailableInContainer() in /Users/[removed]/Sites/[r]]/[r]]/Tests/UnitTests/Plugins/PluginManagerTests.cs:line 18
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Обновления
  • Я удалил абстрактный класс, потому что после удаления это из моей кодовой базы и непосредственная реализация интерфейса, я продолжаю получать ту же ошибку; следовательно, эта ошибка не связана с абстрактными методами. Код был обновлен, чтобы отразить непосредственную реализацию, и я подтвердил, что та же ошибка продолжает возникать.
  • Я подтвердил, что если я удалю метод из интерфейса приложения работает как положено - ошибка возникает только тогда, когда я добавляю метод createQuiz.
  • Поскольку это архитектура плагинов, я понимаю, что важно обеспечить, чтобы файлы .dll плагинов не копировались в другие сборки. Я подтвердил, что этого не происходит:
Изображение

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

Код: Выделить всё

  

**false**
**runtime**





net8.0
**true**
enable

По крайней мере 1 метод работает, здесь я вижу, что GetConfiguration возвращает ожидаемый результат:
Изображение

Я изменил метод, выполнил очистку dotnet && dotnet rebuild и снова запустил тесты, я получил ожидаемый результат:
[img]https://i.sstatic. net/eAbJpiJv.png[/img]
  • Чтобы увидеть, имеет ли это какое-то отношение к тому, что Иван упомянул в комментариях, я провел быстрый тест. Я отредактировал свой интерфейс, добавив новый метод и удалив метод CreateQuiz. Затем я реализовал новый метод, dotnet clean && dotnet rebuild и повторно запустил интеграционный тест — новый метод найден/загружен правильно:
Изображение


Подробнее здесь: https://stackoverflow.com/questions/790 ... y-gettypes
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»