反射和转换在.NET 7和.NET框架中有区别吗?我正在移植一个项目,并在代码结束后得到这个转换错误。最重要的是这个类实现了那个接口。此代码在.NET 4.x中工作。
foreach (Assembly pluginAssembly in pluginAssemblies)
{
try
{
// Look for class(s) with our interface and construct them
foreach (var type in pluginAssembly.GetTypes())
{
Type iDesigner = type.GetInterface(typeof(IFireworksDesigner).FullName);
if (iDesigner != null)
{
object instance = Activator.CreateInstance(type); // creates an object
IFireworksDesigner designer = (IFireworksDesigner)instance; // throws an exception
// do stuff
}
}
}
catch(Exception ex)
{
//Something really bad must have happened.
MessageBox.Show("Fatal error reflecting plugins in assembly '" + pluginAssembly.FullName + "'.\r\n" +
"The error message is:\r\n\r\n" + ex.Message);
}
}更新:我在https://github.com/chrpai/reflection做了一个示例回复
使用调用FW48标准2.0的.NET EXE,它可以工作。如果Core7 EXE调用.NET标准2.0或.NET 7 DLL,则会失败。
发布于 2022-11-26 06:25:37
我得到了原因,结论是类实现的接口以及您试图在不同的AssemblyLoadContext中转换的接口,所以失败了。
详细信息
LoadFile说:
LoadFile不将文件加载到load上下文中。
这意味着LoadFile将把一个程序集加载到一个新的上下文中,源代码也会验证这一点。
AssemblyLoadContext alc = new IndividualAssemblyLoadContext($"Assembly.LoadFile({normalizedPath})");
result = alc.LoadFromAssemblyPath(normalizedPath);在通过LibCore.dll加载LoadFile之后,程序中存在两个AssemblyLoadContext,它们都有一个具有相同名称和相同程序集名称的接口IPlugin。因此,即使使用type.GetInterface(typeof(IPlugin).FullName),代码AssemblyQualifiedName也无法区分不同的上下文。
使用以下代码进行验证。
// IndividualAssemblyLoadContext #2
Console.WriteLine(AssemblyLoadContext.GetLoadContext(iDesigner.Assembly));
// DefaultAssemblyLoadContext #0
Console.WriteLine(AssemblyLoadContext.GetLoadContext(typeof(IPlugin).Assembly));解决方案1
使用LoadFrom而不是LoadFile。LoadFrom将程序集加载到load上下文中,因此接口可以共享。
pluginAssemblies.Add(Assembly.LoadFrom(file));解决方案2
使用一个不可分割的核心库,例如,您可以有3个项目。
ConsoleCoreCore.exe
LibCore.dll
public interface IPlugin
public class Server
Lib1.dll
public class LibStandardPlugin : IPluginLib1.dll和ConsoleCoreCore.exe都引用了LibCore.dll
ConsoleCoreCore.exe -> LibCore.dll <- Lib1.dll现在,如果您通过LibCore.dll通过LoadFile加载Lib1.dll,则Lib1.dll将加载到一个不可分割的上下文中,但它的IPlugin接口仍然是来自LibCore.dll的接口。
// IndividualAssemblyLoadContext #1
Console.WriteLine(AssemblyLoadContext.GetLoadContext(type.Assembly));
// DefaultAssemblyLoadContext #0
Console.WriteLine(AssemblyLoadContext.GetLoadContext(iDesigner.Assembly));
// DefaultAssemblyLoadContext #0
Console.WriteLine(AssemblyLoadContext.GetLoadContext(typeof(IPlugin).Assembly));https://stackoverflow.com/questions/74554851
复制相似问题