首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在使用反射后,.NET 7中出现了一个强制转换错误?

为什么在使用反射后,.NET 7中出现了一个强制转换错误?
EN

Stack Overflow用户
提问于 2022-11-24 02:01:54
回答 1查看 73关注 0票数 1

反射和转换在.NET 7和.NET框架中有区别吗?我正在移植一个项目,并在代码结束后得到这个转换错误。最重要的是这个类实现了那个接口。此代码在.NET 4.x中工作。

代码语言:javascript
复制
    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,则会失败。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-26 06:25:37

我得到了原因,结论是类实现的接口以及您试图在不同的AssemblyLoadContext中转换的接口,所以失败了。

详细信息

LoadFile说:

LoadFile不将文件加载到load上下文中。

这意味着LoadFile将把一个程序集加载到一个新的上下文中,源代码也会验证这一点。

代码语言:javascript
复制
AssemblyLoadContext alc = new IndividualAssemblyLoadContext($"Assembly.LoadFile({normalizedPath})");
result = alc.LoadFromAssemblyPath(normalizedPath);

在通过LibCore.dll加载LoadFile之后,程序中存在两个AssemblyLoadContext,它们都有一个具有相同名称和相同程序集名称的接口IPlugin。因此,即使使用type.GetInterface(typeof(IPlugin).FullName),代码AssemblyQualifiedName也无法区分不同的上下文。

使用以下代码进行验证。

代码语言:javascript
复制
// IndividualAssemblyLoadContext #2
Console.WriteLine(AssemblyLoadContext.GetLoadContext(iDesigner.Assembly));
// DefaultAssemblyLoadContext #0
Console.WriteLine(AssemblyLoadContext.GetLoadContext(typeof(IPlugin).Assembly));

解决方案1

使用LoadFrom而不是LoadFileLoadFrom将程序集加载到load上下文中,因此接口可以共享。

代码语言:javascript
复制
pluginAssemblies.Add(Assembly.LoadFrom(file));

解决方案2

使用一个不可分割的核心库,例如,您可以有3个项目。

代码语言:javascript
复制
ConsoleCoreCore.exe

LibCore.dll
    public interface IPlugin
    public class Server

Lib1.dll
    public class LibStandardPlugin : IPlugin

Lib1.dll和ConsoleCoreCore.exe都引用了LibCore.dll

代码语言:javascript
复制
ConsoleCoreCore.exe -> LibCore.dll <- Lib1.dll

现在,如果您通过LibCore.dll通过LoadFile加载Lib1.dll,则Lib1.dll将加载到一个不可分割的上下文中,但它的IPlugin接口仍然是来自LibCore.dll的接口。

代码语言:javascript
复制
// 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));
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74554851

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档