c# - 如何访问合并的 DLL 中的嵌入式资源?
问题描述
我已经设法使用 AssemblyResolve 事件将 DLL 文件作为嵌入式资源合并到一个 DLL 中,但是当我尝试在另一个控制台应用程序中使用该 Dll 时,我无法访问这个合并的 Dll 所具有的嵌入式资源。例如,这个合并的 Dll 包含我需要使用的类库的另一个 Dll,并且我想访问这个类库具有的公共方法/接口等,但似乎我无法从这个合并的 Dll 访问它们。如何解决这个问题?
static Dictionary<string, Assembly> dic = null;
static void Main(string[] args)
{
var filesList = Directory.EnumerateFiles( //path to Resources folder inside console application, which holds all DLLs that are set as embedded resources );
foreach (var file in filesList)
{
var fname = Path.GetFileNameWithoutExtension(file);
var embRes = "ConsoleAppTest.Resources." + fname + ".dll";
Console.WriteLine(embRes);
Load(embRes, fname + ".dll");
}
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
Console.ReadKey();
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return GetAssembly(args.Name);
}
static void Load(string embeddedResource, string fileName)
{
if (dic == null)
dic = new Dictionary<string, Assembly>();
byte[] assemblyData = null;
Assembly asm = null;
Assembly curAsm = Assembly.GetExecutingAssembly();
using (Stream stream = curAsm.GetManifestResourceStream(embeddedResource))
{
// Either the file is not existed or it is not mark as embedded resource
if (stream == null)
throw new Exception(embeddedResource + " is not found in Embedded Resources.");
// Get byte[] from the file from embedded resource
assemblyData = new byte[(int)stream.Length];
stream.Read(assemblyData, 0, (int)stream.Length);
try
{
asm = Assembly.Load(assemblyData);
// Add the assembly/dll into dictionary
dic.Add(asm.FullName, asm);
Console.WriteLine(asm.FullName);
return;
}
catch
{
// Purposely do nothing
// Unmanaged dll or assembly cannot be loaded directly from byte[]
// Let the process fall through for next part
}
}
bool fileOk = false;
string tempFile = "";
//load unmanaged assemblies
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
{
string fileHash = BitConverter.ToString(sha1.ComputeHash(assemblyData)).Replace("-", string.Empty); ;
tempFile = Path.GetTempPath() + fileName;
if (File.Exists(tempFile))
{
byte[] bb = File.ReadAllBytes(tempFile);
string fileHash2 = BitConverter.ToString(sha1.ComputeHash(bb)).Replace("-", string.Empty);
if (fileHash == fileHash2)
{
fileOk = true;
}
else
{
fileOk = false;
}
}
else
{
fileOk = false;
}
}
if (!fileOk)
{
System.IO.File.WriteAllBytes(tempFile, assemblyData);
}
asm = Assembly.LoadFile(tempFile);
dic.Add(asm.FullName, asm);
Console.WriteLine(asm.FullName);
}
static Assembly GetAssembly(string assemblyFullName)
{
if (dic == null || dic.Count == 0)
return null;
if (dic.ContainsKey(assemblyFullName))
return dic[assemblyFullName];
return null;
}
此控制台应用程序位于 .NET Framework 4.5.1 中,当我构建解决方案时,它会生成一个 .exe 文件。然后我将项目的输出类型更改为类库,以获取 Dll 而不是 exe 并再次构建它。在我得到这个合并的 Dll ConsoleAppTest.dll 后,我在另一个测试项目中添加了对它的引用,但我无法访问 ConsoleAppTest 内部的 dll。例如,如果它里面有 ClientLibrary.dll,我想访问这个 ClientLibrary.dll 的公共方法/接口
using ConsoleAppTest;
//code to access public methods/interfaces of a dll that is inside ConsoleAppTest.dll included in using statement above
解决方案
推荐阅读
- javascript - 在Javascript中碰撞两个div
- matlab - 如何在 MATLAB 中测量图像掩码中线段的长度?
- c# - Unity 将麦克风输入转换为赫兹
- python - 如何使用 %BASH 将包含特定字符串的行从 .csv 文件复制到 Python 中的 .txt 文件?
- asp.net-core - IdentityServer4 - 如何创建可用于查询持久授权表的新端点
- python - 如何在flask/socketio应用程序中使用服务器端对象的锁?
- python - 如何使用 winwifi 包中的 scan() 方法
- f# - 当 stream.UserState 更新时,FParsec 'many' 原语失败
- qml - QML: Implement custom control with rectangles
- c++ - 为什么我们需要语法产生式基本说明符的最后两个定义?