可以在不使用接口的情况下加载程序集吗?
Can assemblies be loaded without using interfaces?
我设置了一个依赖于接口的小型插件系统。但是我发现接口无法序列化,我的整个保存系统都依赖于序列化文件,其中将包含这些插件。
所以我决定将接口换成抽象 class。效果很好。不过我目前的方案好像需要接口。
程序集的类型只显示 null 和 Resources。所以我只是猜测以这种方式加载程序集不能用 abstract classes 来完成?有没有不使用接口的方法?
public List<EnginePluginBase> GetEnginePlugins(string directory)
{
if (string.IsNullOrEmpty(directory))
return null;
List<EnginePluginBase> plugins = new List<EnginePluginBase>();
foreach (FileInfo file in new DirectoryInfo(directory).GetFiles("*.dll"))
{
Assembly currentAssembly = Assembly.LoadFile(file.FullName);
foreach (Type type in GetTypesLoaded(currentAssembly))
{
if (type != typeof(EnginePluginBase))
continue;
EnginePluginBase plugin = (EnginePluginBase)Activator.CreateInstance(type);
plugins.Add(plugin);
}
}
return plugins;
}
private Type[] GetTypesLoaded(Assembly assembly)
{
Type[] types;
try
{
types = assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
types = e.Types.Where(t => t != null).ToArray();
}
return types;
}
将 type !=typeof(EnginePluginBase)
更改为 type.BaseType !=typeof(EnginePluginBase)
作为其基础 class 也不确定此方法是什么 GetTypesLoaded
。
这是我使用并为我工作的代码,我认为应该适合你。
Assembly asm = null;
asm = Assembly.LoadFrom(strProtocolDll);
Type[] assemblyTypes = asm.GetTypes();
foreach (Type module in assemblyTypes)
{
if (typeof(ProtocolBase) == module.BaseType)
{
return (ProtocolBase)Activator.CreateInstance(module);
}
}
您的 GetTypesLoaded 似乎对例外情况过于宽容:
如果加载类型出现异常,需要了解原因。
尝试检查你得到的异常(e.LoaderExceptions
是一个很好的候选者)
正如我在评论中所说,修改您要查找的类型的检查:
改变
if (type != typeof(EnginePluginBase))
continue;
至
if (! typeof(EnginePluginBase).IsAssignableFrom(type))
continue;
这应该适用于抽象基础 class (EnginePluginBase
) 或接口(例如 IEnginePlugin
)
此外,它适用于不直接从 EnginePluginBase
继承的类型 - 即 class 继承自另一个 class,而另一个 class 继承自 EnginePluginBase
(或实现 IEnginePlugin
)
我设置了一个依赖于接口的小型插件系统。但是我发现接口无法序列化,我的整个保存系统都依赖于序列化文件,其中将包含这些插件。
所以我决定将接口换成抽象 class。效果很好。不过我目前的方案好像需要接口。
程序集的类型只显示 null 和 Resources。所以我只是猜测以这种方式加载程序集不能用 abstract classes 来完成?有没有不使用接口的方法?
public List<EnginePluginBase> GetEnginePlugins(string directory)
{
if (string.IsNullOrEmpty(directory))
return null;
List<EnginePluginBase> plugins = new List<EnginePluginBase>();
foreach (FileInfo file in new DirectoryInfo(directory).GetFiles("*.dll"))
{
Assembly currentAssembly = Assembly.LoadFile(file.FullName);
foreach (Type type in GetTypesLoaded(currentAssembly))
{
if (type != typeof(EnginePluginBase))
continue;
EnginePluginBase plugin = (EnginePluginBase)Activator.CreateInstance(type);
plugins.Add(plugin);
}
}
return plugins;
}
private Type[] GetTypesLoaded(Assembly assembly)
{
Type[] types;
try
{
types = assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
types = e.Types.Where(t => t != null).ToArray();
}
return types;
}
将 type !=typeof(EnginePluginBase)
更改为 type.BaseType !=typeof(EnginePluginBase)
作为其基础 class 也不确定此方法是什么 GetTypesLoaded
。
这是我使用并为我工作的代码,我认为应该适合你。
Assembly asm = null;
asm = Assembly.LoadFrom(strProtocolDll);
Type[] assemblyTypes = asm.GetTypes();
foreach (Type module in assemblyTypes)
{
if (typeof(ProtocolBase) == module.BaseType)
{
return (ProtocolBase)Activator.CreateInstance(module);
}
}
您的 GetTypesLoaded 似乎对例外情况过于宽容:
如果加载类型出现异常,需要了解原因。
尝试检查你得到的异常(e.LoaderExceptions
是一个很好的候选者)
正如我在评论中所说,修改您要查找的类型的检查: 改变
if (type != typeof(EnginePluginBase))
continue;
至
if (! typeof(EnginePluginBase).IsAssignableFrom(type))
continue;
这应该适用于抽象基础 class (EnginePluginBase
) 或接口(例如 IEnginePlugin
)
此外,它适用于不直接从 EnginePluginBase
继承的类型 - 即 class 继承自另一个 class,而另一个 class 继承自 EnginePluginBase
(或实现 IEnginePlugin
)