繁体   English   中英

将C#类库嵌入到程序集中并动态加载它们

[英]Embedding C# class libraries into an assembly and loading them dynamically

下午好,

我已经成功将C#类dll文件嵌入到我的应用程序中,可以通过以下方式将其打印出来:

Console.WriteLine(Assembly.GetExecutingAssembly()
    .GetManifestResourceInfo("TestReferenceLib.dll").ResourceLocation);

但是,即使我这样加载它:

public static void Main(string[] args)
{
    Console.WriteLine(Assembly.GetExecutingAssembly().GetManifestResourceInfo("TestReferenceLib.dll").ResourceLocation);

    //This doesn't even fire
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler((o, e) =>
    {
        Console.WriteLine("Resolving?");

        var memory = new MemoryStream();
        Assembly.GetExecutingAssembly().GetManifestResourceStream(e.Name + ".dll").CopyTo(memory);


        if(memory.Length > 0)
            return Assembly.Load(memory.ToArray());

        return null;
    });

    Console.WriteLine("Test assembly compiled and ran succesfully!");

    //Pops errors
    TestReferenceLib.TestReferenceLibrary.PrintOut();
}

标有注释“错误提示”的行显示:

FileNotFoundException:无法加载文件或程序集'TestReferenceLib,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'或其依赖项之一。 该系统找不到指定的文件。

我知道我可以通过使用Assembly.Load()返回的程序集来解决它。 并运行GetType(),GetMethod()和Invoke()使其运行-或使用ILMerge之类的工具或类似工具使其运行-但无需过多深入,对我来说至关重要的是不要使用任何外部工具。

通过“使用TestReferenceLib”的引用可以工作。

预先感谢您提供任何提示。

更新资料

通过这小段代码,我设法将其列出在已加载的程序集中,但是执行仍然不起作用:

var memory = new MemoryStream();

Assembly.GetExecutingAssembly().GetManifestResourceStream("TestReferenceLib.dll").CopyTo(memory);

var assembly = AppDomain.CurrentDomain.Load(memory.ToArray());

foreach (var a in Assembly.GetExecutingAssembly().GetReferencedAssemblies())
{
    Console.WriteLine(a.FullName);
}

foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
    Console.WriteLine(a.FullName);
}

您如何通过编译器将该调用推送到TestReferenceLib.TestReferenceLibrary 您未显示的地方是否有界面?

除此之外,有关解析程序集加载的MSDN文档指出,仅当您尝试按名称加载程序集时才调用AssemblyResolve

您没有在任何地方进行此操作,因此听起来像在调用TestReferenceLib之前需要AppDomain.Load()AppDomain.CreateInstance()或类似的TestReferenceLib

我找到了一个令人满意的解决方案,所以如果有人撞墙,就在这里。

如果要动态编译代码-需要引用类库的代码,这些类库又应作为资源嵌入到程序集中,请确保禁用GenerateInMemory并不要通过调用立即执行文件。

如果要(像我一样)编译一个程序集,然后立即执行它,将其生成为一个文件,创建一个AppDomain并在其中执行它,如下所示:

var assembly = Compiler.Create(files, references, resources, "TestAssembly.TestEntryPoint");

var domain = AppDomain.CreateDomain("ScriptDOM");

domain.ExecuteAssembly(assembly.Location);

这是编译器参数:

var parameters = new CompilerParameters();
parameters.ReferencedAssemblies.AddRange(references);
parameters.EmbeddedResources.AddRange(resources);
parameters.GenerateExecutable = true;
parameters.GenerateInMemory = false;
parameters.IncludeDebugInformation = true;
parameters.CompilerOptions = "/optimize";
parameters.MainClass = entryPoint;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM