using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
 
namespace Utility
{
public class Loader
{
const string LibsFolder = "Libs";
 
static readonly Dictionary<string, Assembly> Libraries = new Dictionary<string, Assembly>();
static readonly Dictionary<string, Assembly> ReflectionOnlyLibraries = new Dictionary<string, Assembly>();
 
public static void Start()
{
AppDomain.CurrentDomain.AssemblyResolve += FindAssembly;
 
PreloadUnmanagedLibraries();
 
var app = new App();
app.Run();
}
 
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string dllToLoad);
 
private static void PreloadUnmanagedLibraries()
{
// Preload correct library
var bittyness = "x86";
if (IntPtr.Size == 8)
bittyness = "x64";
 
var assemblyName = Assembly.GetExecutingAssembly().GetName();
 
var libraries = Assembly.GetExecutingAssembly().GetManifestResourceNames()
.Where(s => s.StartsWith(String.Format("{1}.{2}.{0}.", bittyness, assemblyName.Name, LibsFolder)))
.ToArray();
 
var dirName = Path.Combine(Path.GetTempPath(), String.Format("{2}.{1}.{0}", assemblyName.Version, bittyness, assemblyName.Name));
if (!Directory.Exists(dirName))
Directory.CreateDirectory(dirName);
 
foreach (var lib in libraries)
{
string dllPath = Path.Combine(dirName, String.Join(".", lib.Split('.').Skip(3)));
 
if (!File.Exists(dllPath))
{
using (Stream stm = Assembly.GetExecutingAssembly().GetManifestResourceStream(lib))
{
// Copy the assembly to the temporary file
try
{
using (Stream outFile = File.Create(dllPath))
{
stm.CopyTo(outFile);
}
}
catch
{
// This may happen if another process has already created and loaded the file.
// Since the directory includes the version number of this assembly we can
// assume that it's the same bits, so we just ignore the excecption here and
// load the DLL.
}
}
}
 
// We must explicitly load the DLL here because the temporary directory
// is not in the PATH.
// Once it is loaded, the DllImport directives that use the DLL will use
// the one that is already loaded into the process.
LoadLibrary(dllPath);
}
}
 
internal static Assembly LoadAssembly(string fullName)
{
Assembly a;
 
var executingAssembly = Assembly.GetExecutingAssembly();
 
var assemblyName = executingAssembly.GetName();
 
var shortName = new AssemblyName(fullName).Name;
if (Libraries.ContainsKey(shortName))
return Libraries[shortName];
 
var resourceName = String.Format("{0}.{2}.{1}.dll", assemblyName.Name, shortName, LibsFolder);
var actualName = executingAssembly.GetManifestResourceNames().FirstOrDefault(n => string.Equals(n, resourceName, StringComparison.OrdinalIgnoreCase));
 
if (string.IsNullOrEmpty(actualName))
{
// The library might be a mixed mode assembly. Try loading from the bitty folders.
var bittyness = "x86";
if (IntPtr.Size == 8)
bittyness = "x64";
 
resourceName = String.Format("{0}.{3}.{1}.{2}.dll", assemblyName.Name, bittyness, shortName, LibsFolder);
actualName = executingAssembly.GetManifestResourceNames().FirstOrDefault(n => string.Equals(n, resourceName, StringComparison.OrdinalIgnoreCase));
 
if (string.IsNullOrEmpty(actualName))
{
Libraries[shortName] = null;
return null;
}
 
// Ok, mixed mode assemblies cannot be loaded through Assembly.Load.
// See http://stackoverflow.com/questions/2945080/ and http://connect.microsoft.com/VisualStudio/feedback/details/97801/
// But, since it's an unmanaged library we've already dumped it to disk to preload it into the process.
// So, we'll just load it from there.
var dirName = Path.Combine(Path.GetTempPath(), String.Format("{2}.{1}.{0}", assemblyName.Version, bittyness, assemblyName.Name));
var dllPath = Path.Combine(dirName, String.Join(".", actualName.Split('.').Skip(3)));
 
if (!File.Exists(dllPath))
{
Libraries[shortName] = null;
return null;
}
 
a = Assembly.LoadFile(dllPath);
Libraries[shortName] = a;
return a;
}
 
using (var s = executingAssembly.GetManifestResourceStream(actualName))
{
var data = new BinaryReader(s).ReadBytes((int)s.Length);
 
byte[] debugData = null;
if (executingAssembly.GetManifestResourceNames().Contains(String.Format("{0}.{2}.{1}.pdb", assemblyName.Name, shortName, LibsFolder)))
{
using (var ds = executingAssembly.GetManifestResourceStream(String.Format("{0}.{2}.{1}.pdb", assemblyName.Name, shortName, LibsFolder)))
{
debugData = new BinaryReader(ds).ReadBytes((int)ds.Length);
}
}
 
if (debugData != null)
{
a = Assembly.Load(data, debugData);
Libraries[shortName] = a;
return a;
}
a = Assembly.Load(data);
Libraries[shortName] = a;
return a;
}
}
 
internal static Assembly ReflectionOnlyLoadAssembly(string fullName)
{
var executingAssembly = Assembly.GetExecutingAssembly();
 
var assemblyName = Assembly.GetExecutingAssembly().GetName();
 
string shortName = new AssemblyName(fullName).Name;
if (ReflectionOnlyLibraries.ContainsKey(shortName))
return ReflectionOnlyLibraries[shortName];
 
var resourceName = String.Format("{0}.{2}.{1}.dll", assemblyName.Name, shortName, LibsFolder);
 
if (!executingAssembly.GetManifestResourceNames().Contains(resourceName))
{
ReflectionOnlyLibraries[shortName] = null;
return null;
}
 
using (var s = executingAssembly.GetManifestResourceStream(resourceName))
{
var data = new BinaryReader(s).ReadBytes((int)s.Length);
 
var a = Assembly.ReflectionOnlyLoad(data);
ReflectionOnlyLibraries[shortName] = a;
 
return a;
}
}
 
internal static Assembly FindAssembly(object sender, ResolveEventArgs args)
{
return LoadAssembly(args.Name);
}
 
internal static Assembly FindReflectionOnlyAssembly(object sender, ResolveEventArgs args)
{
return ReflectionOnlyLoadAssembly(args.Name);
}
}
}

Loader for loading embedded assemblies z的更多相关文章

  1. sencha警告:[WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.field.Text'

    chrome开发者工具下提示: [WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.field.Text'; consider addi ...

  2. Best Practices for Assembly Loading

    原文链接 This article discusses ways to avoid problems of type identity that can lead to InvalidCastExce ...

  3. ExtJS笔记 Ext.Loader

    Ext.Loader is the heart of the new dynamic dependency loading capability in Ext JS 4+. It is most co ...

  4. 63.1拓展之纯 CSS 创作一个摇摇晃晃的 loader

    效果地址:https://scrimba.com/c/cqKv4VCR HTML code: <div class="loader"> <span>Load ...

  5. 63.(原65)纯 CSS 创作一个摇摇晃晃的 loader

    原文地址:https://segmentfault.com/a/1190000015424389 修改后地址:https://scrimba.com/c/cqKv4VCR HTML code: < ...

  6. [Angular] Show a Loading Indicator for Lazy Routes in Angular

    We can easily code split and lazy load a route in Angular. However when the user then clicks that la ...

  7. 前端每日实战:65# 视频演示如何用纯 CSS 创作一个摇摇晃晃的 loader

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览.https://codepen.io/comehope/pen/oyJvpe 可交互视频 此视频是可以 ...

  8. mono环境变量

    mono环境变量 2013-05-11 01:14:33|  分类: mono|举报|字号 订阅     下载LOFTER我的照片书  |     Name mono - Mono's ECMA-CL ...

  9. 转载:.NET Memory Leak: XmlSerializing your way to a Memory Leak

    原文地址:http://blogs.msdn.com/b/tess/archive/2006/02/15/532804.aspx I hate to give away the resolution ...

随机推荐

  1. 黑马程序员 c#单态的设计模式 (专题二)

    <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a> ...

  2. Js setInterval与setTimeout(定时执行与循环执行)的代码(可以传入参数)

    最近在做项目时用到了定时执行的js方法,setInterval与setTimeout时间长了不用有些生疏了,所以自己总结了一下,记下来,以便以后使用. Document自带的方法: 循环执行:var ...

  3. WEB开发人员必知的20+HTML5技巧(转)

    互联网科技发展的速度真可谓惊人的快,一个稍不留神,你就可能无法跟上它的步伐. HTML5的变化和更新也压倒不少人,这篇文章将向大家介绍一些最基本也非常必要的 HTML技巧. 1. 新的文档类型(Doc ...

  4. Windows 2008 R2系统开机时如何不让Windows进行磁盘检测?

    开始→运行,在运行对话框中键入“chkntfs /t:0”,即可将磁盘扫描等待时间设置为0, 如果要在计算机启动时忽略扫描某个分区,比如C盘,可以输入“chkntfs /x c:”命令:如果要恢复对C ...

  5. The 5th Zhejiang Provincial Collegiate Programming Contest------ProblemK:Kinds of Fuwas

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1974 题意:问四个角都有同一个福娃的矩形有多少个. #include<b ...

  6. The 5th Zhejiang Provincial Collegiate Programming Contest------ProblemA:Accurately Say "CocaCola"!

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2965 题意:一群人玩过“7”的游戏,有7的数字或者7的倍数就要喊“coca ...

  7. Hibernate-Validation的使用

    首先是要加入下面两个包 hibernate-validator-4.1.0.Final.jar validation-api-1.0.0.GA.jar 如果在验证不通过的时候进行了添加.更新或删除操作 ...

  8. Flume学习——BasicChannelSemantics

    public class MemoryChannel extends BasicChannelSemantics public abstract class BasicChannelSemantics ...

  9. PHP 性能分析第三篇: 性能调优实战

    注意:本文是我们的 PHP 性能分析系列的第三篇,点此阅读 PHP 性能分析第一篇: XHProf & XHGui 介绍 ,或  PHP 性能分析第二篇: 深入研究 XHGui. 在本系列的 ...

  10. altium designer 13 学习之添加汉字

    在altium desginer中如果你是想添加英文还是比较方便的,基本直接就可以输入了,但是添加中文就不是那么简单了,下面不介绍下如何在altium designer中快速的添加自己想要的中文 工具 ...