zoukankan      html  css  js  c++  java
  • 解决反射时ReflectionTypeLoadException异常

    在GIS开发程序中,为了增加扩展性,往往采用插件式开发模式,自然用到了反射技术。如果反射使用的dll控制不好,很容易引发反射异常,查找原因十分不方便,可以使用PrettyBin或Costura等组件实现对类库的管理。

    问题描述

    使用主程序Main.exe反射调用A.dll文件时,出现"未处理 System.Reflection.ReflectionTypeLoadException Message="无法加载一个或多个请求的类型。有关更多信息,请检索LoaderExceptions属性。",代码如下:

    var assembly = Assembly.LoadFile(filePath);
    var types= assembly.GetTypes(); //引发ReflectionTypeLoadException异常

    进一步查看LoaderExceptions异常,发现是因为缺少B.dll或它的某一个依赖项。

    未能加载文件或程序集"B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"或它的某一个依赖项。系统找不到指定的文件。

    A.dll确实引用了B.dll,但仔细核对和检查了所有dll文件都在A.dll所在目录,没有发现缺失的情况。

    这种错误一般只有两种原因:一是dll文件不能被调用主程序找到二是dll文件能找到,但版本不对。实际上,B.dll和A.dll虽然是在相同目录,但与Main.exe不同,使用Main.exe反射调用其他算子时,它只会在Main.exe所在目录 去找B.dll,当然找不到,所以报错。

    解决方案

    方法一: AssemblyResolve事件

    一种解决方法是注册当前域(AppDomain.CurrentDomain)的AssemblyResolve事件,即当反射调用A.dll文件时,它找不到B.dll,就会触发此事件,在这个事件中手动找路径。这种方法的缺点时,需要手动指定路径,不方便修改。

    方法二: privatePath配置

    为了动态修改目录,可直接在AppConfig配置中指定dll所在的目录,如下:

    <configuration>
    …..
    	<runtime>
    		<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    			<probing privatePath="目录1; 目录2" />
    		</assemblyBinding>
    	</runtime>
    </configuration>

    当程序在exe所在的目录找不到dll时,它会依次在目录1、目录2中找,如果还找不到就报错!

    当然也可以用代码来实现,自动添加软件目录下所有文件夹作为privatePath的值。

    参考连接

    关于跨程序集的反射 - torome - 博客园 (cnblogs.com)

    AppDomain.CurrentDomain.AssemblyResolve - mCat - 博客园 (cnblogs.com)

    c# 用代码来设置程序的PrivatePath_夏仲达的博客-CSDN博客_privatepath

    作者:我也是个傻瓜
    出处:http://www.cnblogs.com/liweis/
    签名:成熟是一种明亮而不刺眼的光辉。

  • 相关阅读:
    Linux菜鸟起飞之路【三】Linux常用命令
    Linux菜鸟起飞之路【二】Linux基本常识
    Linux菜鸟起飞之路【一】基本知识与Linux的安装
    交换机和路由器区别
    netdom join more ou
    keepalive.conf配置模板
    mysql7.7.22 Gtid主从搭建
    python 列表处理
    python openpyxl模块使用
    mysql5.7
  • 原文地址:https://www.cnblogs.com/liweis/p/14878085.html
Copyright © 2011-2022 走看看