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();
}
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 для плагинов:
По крайней мере 1 метод работает, здесь я вижу, что GetConfiguration возвращает ожидаемый результат:
Я изменил метод, выполнил очистку dotnet && dotnet rebuild и снова запустил тесты, я получил ожидаемый результат:
[img]https://i.sstatic. net/eAbJpiJv.png[/img]
Чтобы увидеть, имеет ли это какое-то отношение к тому, что Иван упомянул в комментариях, я провел быстрый тест. Я отредактировал свой интерфейс, добавив новый метод и удалив метод CreateQuiz. Затем я реализовал новый метод, dotnet clean && dotnet rebuild и повторно запустил интеграционный тест — новый метод найден/загружен правильно:
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}"); } } }
[/code] Интерфейс плагинов выглядит следующим образом: [b]ILmsPlugin.cs[/b] < pre class="lang-none Prettyprint-override">[code]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(); } [/code] И конкретный класс: [code] 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; } }
[/code] Это ошибка: [code]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) [/code] [b]Обновления[/b] [list] [*]Я удалил абстрактный класс, потому что после удаления это из моей кодовой базы и непосредственная реализация интерфейса, я продолжаю получать ту же ошибку; следовательно, эта ошибка не связана с абстрактными методами. Код был обновлен, чтобы отразить непосредственную реализацию, и я подтвердил, что та же ошибка продолжает возникать.
[*]Я подтвердил, что если я удалю метод из интерфейса приложения работает как положено - ошибка возникает только тогда, когда я добавляю метод createQuiz.
[*] Поскольку это архитектура плагинов, я понимаю, что важно обеспечить, чтобы файлы .dll плагинов не копировались в другие сборки. Я подтвердил, что этого не происходит:
Согласно инструкциям, найденным здесь, я настроил файлы .csproj для плагинов: [code]
**false** **runtime**
net8.0 **true** enable
[/code] По крайней мере 1 метод работает, здесь я вижу, что GetConfiguration возвращает ожидаемый результат: [img]https://i.sstatic.net/BOirmBZz.png[/img]
Я изменил метод, выполнил очистку dotnet && dotnet rebuild и снова запустил тесты, я получил ожидаемый результат: [img]https://i.sstatic. net/eAbJpiJv.png[/img]
[list] [*]Чтобы увидеть, имеет ли это какое-то отношение к тому, что Иван упомянул в комментариях, я провел быстрый тест. Я отредактировал свой интерфейс, добавив новый метод и удалив метод CreateQuiz. Затем я реализовал новый метод, dotnet clean && dotnet rebuild и повторно запустил интеграционный тест — новый метод найден/загружен правильно: [/list] [img]https://i.sstatic.net/YjjXnIIx.png[/img]