在.Net Framework时代,生成类库只需将类库项目编译好,然后拷贝到其他项目,即可引用或动态加载,相对来说,比较简单。但到了.Net Core时代,动态加载第三方类库,则稍微麻烦一些。

一、类库发布丢失Nuget依赖包

   对于大部分类库来说,项目或多或少会引用第三方程序集,特别是Nuget程序包。通常编译类库项目生成的文件中,并不会包含引用的Nuget包相关类库,而是通过*.deps.json文件来描述类库所需的依赖。这样造成一种问题,如果该类库是通过动态加载的方式引用,则程序运行时,会提示“缺少某某dll”的问题。

  解决上述问题,需要在该类库项目的.csproj文件中,在<PropertyGroup></PropertyGroup>标签中加入<EnableDynamicLoading>true</EnableDynamicLoading>标志,该属性将告诉编译器,该项目是动态加载的组件。相关链接:https://docs.microsoft.com/zh-cn/dotnet/core/project-sdk/msbuild-props#enabledynamicloading

二、类库编译生成多余的dll

  对于类库项目来说,通常会引用解决方案中其他通用项目,而主体程序也会引用这些通用项目,所以对于类库来说,在编译生成的文件中,并不需要这些文件。这种情况下,也需要修改.csproj项目文件,如下图,生成的类库文件将不会包含pluginBase.csproj类库及其所有的依赖;

三、利用反射动态加载类库

  如果按照文末参考文献中的教程,我尝试过仍会出现找不到“某某.dll”的问题,这边贴出我的代码,供参考:

 1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Reflection;
5 using System.Runtime.Loader;
6
7 namespace LoadDLL
8 {
9 /// <summary>
10 /// 程序集加载器
11 /// </summary>
12 public class AssemblyLoader
13 {
14 private string _basePath;
15 private AssemblyLoadContext context;
16
17
18 public AssemblyLoader(string basePath)
19 {
20 _basePath = basePath;
21 }
22
23 public Type Load(string dllFileName, string typeName)
24 {
25 context = new AssemblyLoadContext(dllFileName);
26 context.Resolving += Context_Resolving;
27 //需要绝对路径
28 string path = Path.Combine(_basePath, dllFileName);
29 if (File.Exists(path))
30 {
31 try
32 {
33 using (var stream = File.OpenRead(path))
34 {
35 Assembly assembly = context.LoadFromStream(stream);
36 Type type = assembly.GetType(typeName);
37 dicTypes.Add(typeName, type);
38 return type;
39 }
40 }
41 catch (Exception ex)
42 {
43 Console.WriteLine($"加载节点{dllFileName}-{typeName}发生异常:{ex.Message},{ex.StackTrace}");
44 }
45
46 }
47 else
48 {
49 Console.WriteLine($"节点动态库{dllFileName}不存在:{path}");
50 }
51 return null;
52 }
53
54 /// <summary>
55 /// 加载依赖文件
56 /// </summary>
57 /// <param name="context"></param>
58 /// <param name="assemblyName"></param>
59 /// <returns></returns>
60 private Assembly Context_Resolving(AssemblyLoadContext context, AssemblyName assemblyName)
61 {
62 string expectedPath = Path.Combine(_basePath, assemblyName.Name + ".dll"); ;
63 if (File.Exists(expectedPath))
64 {
65 try
66 {
67 using (var stream = File.OpenRead(expectedPath))
68 {
69 return context.LoadFromStream(stream);
70 }
71 }
72 catch (Exception ex)
73 {
74 Console.WriteLine($"加载节点{expectedPath}发生异常:{ex.Message},{ex.StackTrace}");
75 }
76 }
77 else
78 {
79 Console.WriteLine($"依赖文件不存在:{expectedPath}");
80 }
81 return null;
82 }
83 }
84 }

其中Context_Resolving(),是用于加载类库文件过程中,处理触发加载相关依赖文件的事件的方法,通过上述代码,可以保证将类库的完整地动态加载进程序,并且不会与其他动态加载类库项目发生程序集冲突的问题:比如A类库和B类库都有共同的依赖C,但两者的引用的C版本不同,通过AssemblyLoadContext可以保证A/B类库加载自己需要的版本。

四、结尾

  在.Net Core动态加载类库还是挺多坑的,以上是我踩过来,与大家分享~

参考文献:

1、使用插件创建 .NET Core 应用程序

.Net Core利用反射动态加载类库的方法(解决类库不包含Nuget依赖包的问题)的更多相关文章

  1. C# 利用反射动态加载dll

    笔者遇到的一个问题,dll文件在客户端可以加载成功,在web端引用程序报错.解决方法:利用反射动态加载dll 头部引用加: using System.Reflection; 主要代码: Assembl ...

  2. java利用反射动态加载方法

    @参考文章 根据特定字符串加载相应的方法,有人用if else,有人用switch.参数少了或情况少了还好,很多方法真要命,不要紧,java反射拯救你 import java.lang.reflect ...

  3. 利用“反射”动态加载R文件中的资源

    前几天做一个Android下面数据库相关的应用.用ListVIew展示表中数据的时候我希望能给表中每一条记录,加一个展示的图片.但是用数据库保存图片是比较难搞的.于是就把所需图片都保存到res下的dr ...

  4. java反射并不是什么高深技术,面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象

    java反射并不是什么高深技术,面向对象语言都有这个功能. 面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象,去获取类相关的信息 2.利用java反射可以调用类 ...

  5. 微信小程序(五) 利用模板动态加载数据

    利用模板动态加载数据,其实是对上一节静态数据替换成动态数据:

  6. js实现动态加载脚本的方法实例汇总

      本文实例讲述了js实现动态加载脚本的方法.分享给大家供大家参考,具体如下: 最近公司的前端地图产品需要做一下模块划分,希望用户用到哪一块的功能再加载哪一块的模块,这样可以提高用户体验. 所以到处查 ...

  7. Linux下C++动态加载so 调用方法

    Windows 下的C++动态加载DLL调用方法 文献参考 http://man7.org/linux/man-pages/man0/dlfcn.h.0p.html http://man7.org/l ...

  8. java反射动态加载类Class.forName();

    1,所有的new出来的对象都是静态加载的,在程序编译的时候就会进行加载.而使用反射机制Class.forName是动态加载的,在运行时刻进行加载. 例子:直接上两个例子 public class Ca ...

  9. 利用javascript动态加载头部出现点击事件与hover事件无效解决方法

    这里是利用es6的promise函数来异步加载,当HTML动态加载过去的HTML片段加载完毕再执行绑定事件的js代码: 具体过程如下 这里是用了jQuery框架的例子 $(function(){ // ...

随机推荐

  1. Qt生成和调用动态库dll,和静态库.a(windows和linux通用)

    系统1:ThinkPad T570.Windows10.QT5.12.2(Qt Creater 4.8.2)一.动态库.dll的创建和调用1.在qtcreater中按如下步骤创建动态库,动态库名为my ...

  2. python创建字典多种方式

    1.创建空字典 >>> dic = {} >>> type(dic) <type 'dict'> 2.直接赋值创建 >>> dic = ...

  3. 默认标签的解析过程(三)parseDefaultElement

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate. ...

  4. 如何打一个RPM包

    如何打一个RPM包 参考链接:RPM打包原理.示例.详解及备查 前言 本文只是一个RPM安装的例子,并没有对RPM做比较详尽的叙述,更为详尽的讲解,可以在上面的链接中找到. RPM是啥? RPM(Re ...

  5. Element form表单方法resetFields无效

    之前遇到resetFields无效时都是自己手动用this.ruleForm = Object.assign({}, this.ruleForm, this.$options.data().ruleF ...

  6. Go版本依赖--伪版本

    目录 1.简介 2. 什么是伪版本 3. 伪版本风格 4. 如何获取伪版本 1.简介 在go.mod中通常使用语义化版本来标记依赖,比如v1.2.3.v0.1.5等.因为go.mod文件通常是go命令 ...

  7. python json demo

    值得注意的一点是,list类型的数据可以用[2,3]的方式定义,如"b" import json jsonData = '{"a":1,"b" ...

  8. Redis的持久化机制与内存管理机制

    1.概述 Redis的持久化机制有两种:RDB 和 AOF ,这两种机制有什么区别?正式环境应该采用哪种机制? 我们的服务器内存资源是有限的,如果内存被Redis的缓存占满了怎么办?这就要看Redis ...

  9. Linux - 解决使用 apt-get 安装 yum 的时耗报 E: Unable to locate package yum 的错误

    问题背景 在 Linux 系统下使用 apt-get 命令安装 yum 库报错 apt-get install yum E: Unable to locate package yum 问题解决 一行命 ...

  10. wireshark 解密加密报文

    wireshark 解密IPSec加密后的报文 序言 wireshark作为一款非常优秀的抓包工具,支持了各种各样的网络协议,成为了网络开发中必不可少的工具之一.一般而言,对于普通的网络数据包,wir ...