当前位置: 首页 > news >正文

C# 子类强制转换为父类异常,引出的C#Dll加载机制,以及同类名同命名空间同dll程序集在C#中是否为同一个类的研究。

已知,子类B继承自父类A,但是在代码运行时,B类强制转换为A类,却报代码转换异常。
很奇怪的问题吧,不过这个也是难得机会,去研究C#运行的底层原理。

下面是报错的代码片段。

string className = _shapeReflectMap[typeName].ClassName;
Assembly assem = _shapeReflectMap[typeName].Assem;
Object obj = assem.CreateInstance(className); // 在dll程序集中 通过className实例化获取子类
Type type1 = obj.GetType().BaseType; // 获取父类类型
Type type2 = typeof(Shape);
Assembly assembly1 = type1.Assembly;
Assembly assembly2 = type2.Assembly;
string codeBase1 = assembly1.CodeBase;
string codeBase2 = assembly2.CodeBase;
try
{shape = (Shape)obj;
}
catch (Exception e)
{throw new Exception("反射创建Shape失败"+ "\n类型直接比较: " + (type1 == type2)+ "\n程序集直接比较: " + (assembly1 == assembly2)+ "\n类型全名比较: " + (type1.FullName == type2.FullName) + ": " + type1.FullName + " " + type2.FullName+ "\n程序集全名比较: " + (assembly1.FullName == assembly2.FullName) + ": " + assembly1.FullName + " " + assembly2.FullName+ "\ncodeBase1: " + codeBase1+ "\ncodeBase2: " + codeBase2+ "\n程序集路径比较: " + (codeBase1 == codeBase2)+ "\ncodeBase1.hash: " + codeBase1.GetHashCode()+ "\ncodeBase2.hash: " + codeBase2.GetHashCode()+ "\n", e);
}

下面是报错结果(其中的敏感字符串被替换成了xxx):

System.Exception: 反射创建Shape失败
类型直接比较: False
程序集直接比较: False
类型全名比较: True: xxx.WpfPlugin.Shape xxx.WpfPlugin.Shape
程序集全名比较: True: xxx.WpfPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null xxx.WpfPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
codeBase1: file:///D:/project/XXX/xxx.xxxClient.UI/xxx.xxxClient.UI/bin/Debug/Plugins/xxx.WpfPlugin.dll
codeBase2: file:///D:/project/XXX/xxx.xxxClient.UI/xxx.xxxClient.UI/bin/Debug/Plugins/xxx.WpfPlugin.dll
程序集路径比较: True
codeBase1.hash: -336973287
codeBase2.hash: -336973287---> System.InvalidCastException: 无法将类型为“xxx.WpfPlugin.Shapes.ImageButton”的对象强制转换为类型“xxx.WpfPlugin.Shape”。在 xxx.WpfPlugin.ctlUI.LoadXml(String xmlPath) 位置 D:\project\XXX\dll\PluginsSources\xxx.WpfPlugin\ctlUI.cs:行号 107--- 内部异常堆栈跟踪的结尾 ---在 xxx.WpfPlugin.ctlUI.LoadXml(String xmlPath) 位置 D:\project\XXX\dll\PluginsSources\xxx.WpfPlugin\ctlUI.cs:行号 111在 xxx.WpfPlugin.ctlUI.DisplayInit() 位置 D:\project\XXX\dll\PluginsSources\xxx.WpfPlugin\ctlUI.cs:行号 177

通过上面的代码可以看出,从子类中获取的父类type,和父类直接获取的type是完全一样的,命名空间,类名称,程序集和对应的dll文件,均相同。但是通过==判断,其在内存中并非同一个对象。

经过排查,发现代码中对该dll加载了两次,获得了两个程序集,而子类和父类分别来自不同的程序集,导致了无法进行类型转换。在修复该dll加载逻辑后问题便得到了解决。

可以推测出,C#判断两个类是否完全相同,除了看命名空间和类名以外,主要是判断两个类是否在同一个程序集实体中(内存中的同一个实体)。若一个dll加载了两遍,获得两个程序集对象,虽然两个程序集中的类完全相同,但是依然无法相互转换。

所以程序集最好有一个公共的存放处,统一的加载逻辑,不要养成需要某个类时直接去加载一遍dll的坏习惯。
也可以通过Assembly.GetExecutingAssembly()直接获取当前代码所在的程序集,避免重复加载。

相关文章:

C# 子类强制转换为父类异常,引出的C#Dll加载机制,以及同类名同命名空间同dll程序集在C#中是否为同一个类的研究。

已知,子类B继承自父类A,但是在代码运行时,B类强制转换为A类,却报代码转换异常。 很奇怪的问题吧,不过这个也是难得机会,去研究C#运行的底层原理。 下面是报错的代码片段。 string className _shapeRefle…...

Go语言进阶

个人笔记,大量摘自Go语言高级编程、Go|Dave Cheney等 更新 go get -u all 在非go目录运行go install golang.org/x/tools/goplslatest更新go tools:在go目录运行go get -u golang.org/x/tools/...,会更新bin目录下的应用; 运行…...

Java的枚举

枚举 对应英文(enumeration, 简写enum) 枚举是一组常量的集合,属于一种特殊的类,里面只包含一组有限的特定的对象。 自定义类实现枚举 1.不需要提供setXxx方法,因为枚举对象值通常为只读. 2.对枚举对象/属性使用 final static共同修饰…...

Pytest测试框架3

目录: pytest结合数据驱动-yamlpytest结合数据驱动-excelpytest结合数据驱动-csvpytest结合数据驱动-jsonpytest测试用例生命周期管理(一)pytest测试用例生命周期管理(二)pytest测试用例生命周期管理(三&a…...

【数学建模】-- Matlab中图的最短路径

前言: 图的基本概念: 若想简单绘制图可以利用此网站: 左上角Undirected/Directed是无向图/有向图 左边 0-index ,1-index为0下标,1下标。 Node Count为节点个数 Graph Data:最初尾节点的名称&#xff…...

中国月入过万的人多不多

Q:中国月入过万的人多不多 单从这个问题来看,这是个费米问题啊: 估算中国月入过万的有多少人? 要解决费米问题,其实也很好办,就是逻辑拆解,这篇文章也分为3个部分,先从公开数据中估…...

苹果电脑图像元数据编辑器:MetaImage for Mac

MetaImage for Mac是一款功能强大的照片元数据编辑器,它可以帮助用户编辑并管理照片的元数据信息,包括基本信息和扩展信息。用户可以根据需要进行批量处理,方便快捷地管理大量照片。 MetaImage for Mac还提供了多种导入和导出格式&#xff0…...

BeanUtils.copyProperties() 详解

BeanUtils.copyProperties会进行类型转换; BeanUtils.copyProperties方法简单来说就是将两个字段相同的对象进行属性值的复制。如果 两个对象之间存在名称不相同的属性,则 BeanUtils 不对这些属性进行处理,需要程序手动处理。 这两个类在不同…...

基于CentOS 7构建LVS-DR集群

DIPVIPRIPClient192.169.41.139 LVS 192.168.41.134192.169.41.10RS1192.168.41.135RS2192.168.41.138 要求: node4为客户端,node2为LVS,node3和node4为RS。 1.配置DNS解析(我这里使用本地解析) 192.168.41.134 www.y…...

openEuler-OECA考试报名火热开启,尊享半价优惠 作者:HopeInfra 发布时间:2023-08-10

近日,润和软件人才评定报名系统已成功上线运行,现openEuler-OECA人才评定考试报名优惠活动火热开启,欢迎大家报名咨询! 关于openEuler人才评定 随着openEuler及其发行版本在各个行业使用量逐年增多,相关人才的评定诉求…...

侯捷 C++面向对象编程笔记——10 继承与虚函数

10 继承与虚函数 10.1 Inheritance 继承 语法::public base_class_name public 只是一种继承的方式,还有protect,private 子类会拥有自己的以及父类的数据 10.1.1 继承下的构造和析构 与复合下的构造和析构相似 构造是由内而外 Container …...

mysql日期函数(查询最近n(天/月/年)、计算日期之间的天数等)

mysql日期函数 目录 mysql查询最近一个月数据返回当前日期和时间将字符串转变为日期日期 d 减去 n 天后的日期计时间差,返回 datetime_expr2 − datetime_expr1 的时间差算查询当天数据 ADDDATE(d,n)计算起始日期 d 加上 n 天的日期 SELECT ADDDATE("2017-06…...

通过anvt X6和vue3实现图编辑

通过anvt X6 X6地址&#xff1a;https://x6.antv.antgroup.com/tutorial/about&#xff1b; 由于节点比较复杂&#xff0c;使用vue实现的节点&#xff1b; x6提供了一个独立的包 antv/x6-vue-shape 来使用 Vue 组件渲染节点。 VUE3的案例&#xff1a; <template><div…...

win2012 IIS8.5 安装PHP教程,一些版本不能用

因为一直用win2003IIS6.0PHP的环境&#xff0c;所以搭建PHP自认为非常熟悉了&#xff0c;但是最近在搭建win2012IIS8.5PHP的环境时&#xff0c;我遇到了一些问题&#xff0c;经过4个小时的折腾&#xff0c;终于搞定了&#xff0c;本文记录一些经验&#xff0c;可能不少朋友也会…...

sqlalchemy执行原生sql

# 有的复杂sql 用orm写不出来---》用原生sql查询 # 原生sql查询&#xff0c;查出的结果是对象 # 原生sql查询&#xff0c;查询结果列表套元组 准备工作 from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engineengine create_engine(&…...

Python-OpenCV中的图像处理-图像平滑

Python-OpenCV中的图像处理-图像平滑 图像平滑平均滤波高斯模糊中值模糊双边滤波 图像平滑 使用低通滤波器可以达到图像模糊的目的。这对与去除噪音很有帮助。其实就是去除图像中的高频成分&#xff08;比如&#xff1a;噪音&#xff0c;边界&#xff09;。所以边界也会被模糊…...

Mongoose http server 例子

今天抽了点时间看了一下 mongoose的源码&#xff0c; github 地址&#xff0c;发现跟以前公司内部使用的不太一样&#xff0c;这里正好利用其 http server 例子来看一下。以前的 http message 结构体是这样的&#xff1a; /* HTTP message */ struct http_message {struct mg_…...

1、初识HTML

1、初识HTML 前端就是写一些基本的页面&#xff0c;HTML即超文本标记语言&#xff1a;Hyper Text Markup Language&#xff0c;超文本包括&#xff0c;文字、图片、音频、视频、动画等&#xff0c;HTML5&#xff0c;提供了一些新的元素和一些有趣的新特性&#xff0c;同时也建…...

线性代数(三) 线性方程组

前言 如何利用行列式&#xff0c;矩阵求解线性方程组。 线性方程组的相关概念 用矩阵方程表示 齐次线性方程组&#xff1a;Ax0&#xff1b;非齐次线性方程组&#xff1a;Axb. 可以理解 齐次线性方程组 是特殊的 非齐次线性方程组 如何判断线性方程组的解 其中R(A)表示矩阵A的…...

Apoll 多项式规划求解

一、纵向规划 void QuarticPolynomialCurve1d::ComputeCoefficients(const float x0, const float dx0, const float ddx0, const float dx1,const float ddx1, const float p) {if (p < 0.0) {std::cout << "p should be greater than 0 at line 140." &…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...