· 在开发“元数据验证工具”时,可执行程序要在各项目现场使用收集数据,其功能单一且操作简单。
· 最初程序包中包含依赖的Dll和配置文件,项目使用这些程序时要复制的文件较多,如果复制过程漏掉文件应用程序就不可使用。
· 为保持这些工具的布署也很简洁,发现可以将应用程序依赖的Dll和配置文件内嵌到应用程序中,在运行时提取这些内嵌资源,动态加载Dll程序集和配置文件,这些工具就是单一的一个可执行程序。
· 具体的实现如下:
1.在vs中,将工程依赖的Dll和配置文件引入到工程中,将这些项目的“生成操作”设置为“嵌入资源”。
2.在运行时加载Dll和配置文件
由于应用程序依赖的Dll都被内嵌到应用程序文件中,应用程序不能解析这些Dll的程序集,需要在程序初始时加载这些Dll的程序集,并订阅AppDomain的AssemblyResolve事件,在此事件中按事件的参数提供Assembly对象,代码如下:
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
LoadCoreLib();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FrmMain());
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (dicCacheAssembly.ContainsKey(args.Name) == true)
{
return dicCacheAssembly[args.Name];
}
else
{
return null;
}
}
private static void LoadCoreLib()
{
var loadResCoreLibs = new string[]
{
"DBVersionCollector.Checker.CoreLib.DBVersionCollector.Core.dll",
"DBVersionCollector.Checker.CoreLib.DBVersionCollector.Data.dll",
"DBVersionCollector.Checker.CoreLib.DBVersionCollector.DB.dll",
"DBVersionCollector.Checker.CoreLib.DBVersionCollector.Helper.dll",
"DBVersionCollector.Checker.CoreLib.DocumentFormat.OpenXml.dll",
};
var exeass = Assembly.GetExecutingAssembly();
foreach (var item in loadResCoreLibs)
{
try
{
using (var stream = exeass.GetManifestResourceStream(item))
{
var buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
var ass = AppDomain.CurrentDomain.Load(buffer);
dicCacheAssembly.Add(ass.FullName, ass);
}
}
catch { }
}
}
对于配置文件,从获取嵌入资源的流对象再做转换获取:
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DBVersionCollector.Checker.CoreLib.Metadata.xml"))
{
var xreader = XmlReader.Create(stream);
var xdoc = XDocument.Load(xreader);
metadata = MetadataConfig.Parse(xdoc);
}