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();
}
BaseLmsPlugin.cs
Код: Выделить всё
public abstract class BaseLmsPlugin : ILmsPlugin
{
private ILmsPluginInstanceConfiguration? Configuration { get; set; }
public abstract string Name { get; }
public abstract string MachineName { get; }
public abstract Type ConfigurationClass { get; }
public abstract Task CreateQuiz(Quiz quiz);
public void SetConfiguration(string? configuration)
{
if (configuration == null)
{
return;
}
Configuration = JsonSerializer.Deserialize(configuration, ConfigurationClass) as ILmsPluginInstanceConfiguration;
}
public ILmsPluginInstanceConfiguration? GetConfiguration()
{
return Configuration;
}
}
Код: Выделить всё
public class LmsPlugin : BaseLmsPlugin
{
public override string Name { get => "Mock LmsPlugin"; }
public override string MachineName { get => "mock_lmsplugin"; }
public override Type ConfigurationClass { get => typeof(MockLmsPluginConfiguration); }
public override Task CreateQuiz(Quiz quiz)
{
ILmsPluginQuizOutputDto dto = new LmsPluginQuizOutput
{
Name = quiz.Name,
CourseId = 1
};
return Task.FromResult(dto);
}
}
Код: Выделить всё
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)
Метод наверняка реализован в моем классе. Я концентрируюсь на абстрактном методе, потому что если в моем абстрактном классе (BaseLmsPlugin.cs)
я изменюсь:
< pre class="lang-none Prettyprint-override">
Код: Выделить всё
public abstract Task CreateQuiz(Quiz quiz);
Код: Выделить всё
public Task CreateQuiz(Quiz quiz) => throw new System.NotImplementedException();
Код: Выделить всё
public new Task CreateQuiz(Quiz quiz)
{
ILmsPluginQuizOutputDto dto = new LmsPluginQuizOutput
{
Name = quiz.Name,
CourseId = 1
};
return Task.FromResult(dto);
}
Можно ли мне объявить абстрактный метод и при этом заставить плагин загружаться через отражение?
п>
Подробнее здесь: https://stackoverflow.com/questions/790 ... y-gettypes
Мобильная версия