C#程序(含多个Dll)合并成一个Exe的简单方法

2019-12-30 15:05:30于海丽

下面这两个函数就是Fody.Costura实现这部分逻辑的代码。


public static void Attach()
{
  var currentDomain = AppDomain.CurrentDomain;
  currentDomain.AssemblyResolve += (s, e) => ResolveAssembly(e.Name);
}
public static Assembly ResolveAssembly(string assemblyName)
{
  if (nullCache.ContainsKey(assemblyName))
  {
   return null;
  }  

  var requestedAssemblyName = new AssemblyName(assemblyName);  

  var assembly = Common.ReadExistingAssembly(requestedAssemblyName);
  if (assembly != null)
  {
   return assembly;
  }  

  Common.Log("Loading assembly '{0}' into the AppDomain", requestedAssemblyName);  

  assembly = Common.ReadFromEmbeddedResources(assemblyNames, symbolNames, requestedAssemblyName);
  if (assembly == null)
  {
   nullCache.Add(assemblyName, true);  

   // Handles retargeted assemblies like PCL
   if (requestedAssemblyName.Flags == AssemblyNameFlags.Retargetable)
   {
     assembly = Assembly.Load(requestedAssemblyName);
   }
  }
  return assembly;
}

可以看到,Attach方法监听了AppDomain.AssemblyResolve事件。当CLR无法成功加载某个程序集时, AssemblyResolve事件处理函数会被执行。AssemblyResolve会尝试通过Common.ReadFromEmbeddedResources方法从已加载的程序集的嵌入资源中获取目标程序集,并返回给CLR。

看到这里,你可能会问,Attach方法是在什么时候执行的呢?

其实是这样的,对于C#语言来说,CLR隐藏了一个大招——CLR可以在每个模块(每个程序集都含有一个或多个模块)加载之前执行一些初始化的代码。但是很遗憾,C#语言无法控制这部分代码。Fody.Costura则是在内部将IL代码直接注入到EXE程序集内部模块的初始化函数中,而这部分IL代码其实就是执行了Attach方法。这样一来,EXE程序集被加载后,Attach方法就能够立即得到调用了。

以上就是Fody.Costura实现原理的简单介绍。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持ASPKU。


注:相关教程知识阅读请移步到c#教程频道。