MEF-从嵌入式DLL获取程序集 [英] MEF - Get assembly from embedded DLL
问题描述
我正在使用MEF为WPF应用程序创建插件".我想将其中一些插件直接嵌入EXE文件,因为EXE需要独立.我正在使用Fody的Costura来嵌入资源以及所有其他参考.由于exe文件需要独立,因此我无法为这些插件创建目录并使用DirectoyCatalog
I am using MEF to create "plugins" for my WPF application. Some of these plugins I want to embed directly into the EXE file as the EXE needs to be standalone. I am using Costura by Fody to embed the resource along with all my other references. As the exe file needs to be standalone I am unable to create a directory for these plugins and use the DirectoyCatalog
无论如何,我可以从嵌入式资源中加载程序集,也可以简单地指定程序集名称,例如:
Is there anyway I can either load the assembly from the embedded resource, or simply specify the assembly name such as:
catalog.Catalogs.Add(new AssemblyCatalog("My.Assembly.Name));
我尝试遍历清单资源,但这些似乎被Fody压缩了:
I have tried looping through the Manifest resources but these appear to be zipped by Fody:
var resourceNames = GetType().Assembly.GetManifestResourceNames();
foreach (var resourceName in resourceNames)
感谢任何帮助/建议.
推荐答案
Ok so got this to work for me, using the class below (found this code at https://github.com/Sebazzz/EntityProfiler/blob/master/src/UI/EntityProfiler.Viewer/AppBootstrapper.cs and tweaked to suit my needs):
要使用它,您只需调用提取函数,该函数将在资源清单中找到任何Costura Zip文件并将其解压缩并注册.
To use it you simply call the extract function which will find any Costura Zip files in resource manifest and decompresses it and registers it.
该函数返回与该函数中传递的字符串匹配的所有程序集的字典.然后,我遍历它们,并将其添加到组合容器要使用的目录中:
The function returns a dictionary of all assemblies that match the string passed in the function. I then iterate over them and add to catalog to be used by composition container:
var assemblies = CosturaAssemblyExtractor.Extract(AppDomain.CurrentDomain, Assembly.GetExecutingAssembly(), "My.AssemblyName");
foreach (var assembly in assemblies)
{
catalog.Catalogs.Add(new AssemblyCatalog(assembly.Value));
}
container = new CompositionContainer(catalog);
班级:
public static class CosturaAssemblyExtractor
{
public static Dictionary<string, Assembly> Extract(AppDomain OrigDomain, Assembly ExecutingAssembly, string AssemblyStartsWith)
{
//var currentDomain = origDomain;
var assemblies = OrigDomain.GetAssemblies();
var references = new Dictionary<string, Assembly>();
var manifestResourceNames = ExecutingAssembly.GetManifestResourceNames().Where(x => {
return x.ToUpper().StartsWith(("costura." + AssemblyStartsWith).ToUpper()) && x.ToUpper().EndsWith(".dll.zip".ToUpper());
});
foreach (var resourceName in manifestResourceNames)
{
var solved = false;
foreach (var assembly in assemblies)
{
var refName = string.Format("costura.{0}.dll.zip", GetDllName(assembly, true));
if (resourceName.Equals(refName, StringComparison.OrdinalIgnoreCase))
{
references[assembly.FullName] = assembly;
solved = true;
break;
}
}
if (solved)
continue;
using (var resourceStream = ExecutingAssembly.GetManifestResourceStream(resourceName))
{
if (resourceStream == null) continue;
if (resourceName.EndsWith(".dll.zip"))
{
using (var compressStream = new DeflateStream(resourceStream, CompressionMode.Decompress))
{
var memStream = new MemoryStream();
CopyTo(compressStream, memStream);
memStream.Position = 0;
var rawAssembly = new byte[memStream.Length];
memStream.Read(rawAssembly, 0, rawAssembly.Length);
var reference = Assembly.Load(rawAssembly);
references[reference.FullName] = reference;
}
}
else
{
var rawAssembly = new byte[resourceStream.Length];
resourceStream.Read(rawAssembly, 0, rawAssembly.Length);
var reference = Assembly.Load(rawAssembly);
references[reference.FullName] = reference;
}
}
}
return references;
}
private static void CopyTo(Stream source, Stream destination)
{
var array = new byte[81920];
int count;
while ((count = source.Read(array, 0, array.Length)) != 0)
{
destination.Write(array, 0, count);
}
}
private static string GetDllName(Assembly assembly, bool withoutExtension = false)
{
var assemblyPath = assembly.CodeBase;
return withoutExtension ? Path.GetFileNameWithoutExtension(assemblyPath) : Path.GetFileName(assemblyPath);
}
}
这篇关于MEF-从嵌入式DLL获取程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!