简体   繁体   English

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

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

Good afternoon, 下午好,

I've succesfully embedded a C# class dll file into my app, I can print out it being there via: 我已经成功将C#类dll文件嵌入到我的应用程序中,可以通过以下方式将其打印出来:

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

But, even if I load it as so: 但是,即使我这样加载它:

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();
}

The line marked with comment 'Pops errors' says: 标有注释“错误提示”的行显示:

FileNotFoundException: Could not load file or assembly 'TestReferenceLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. FileNotFoundException:无法加载文件或程序集'TestReferenceLib,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'或其依赖项之一。 The system cannot find the file specified. 该系统找不到指定的文件。

I know that I could walk around it by taking the assembly returned by Assembly.Load(); 我知道我可以通过使用Assembly.Load()返回的程序集来解决它。 and run GetType(), GetMethod() and Invoke() to make it work - or use tools like ILMerge or similar to make it work - but without going too much in depth, it's crucial for me not to use any external tools. 并运行GetType(),GetMethod()和Invoke()使其运行-或使用ILMerge之类的工具或类似工具使其运行-但无需过多深入,对我来说至关重要的是不要使用任何外部工具。

The reference via 'using TestReferenceLib' HAS to work. 通过“使用TestReferenceLib”的引用可以工作。

Thank you in advance for any tips. 预先感谢您提供任何提示。

Update 更新资料

With this little piece of code I manage to get it listed in loaded assemblies, but executing still doesn't work: 通过这小段代码,我设法将其列出在已加载的程序集中,但是执行仍然不起作用:

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);
}

How are you pushing that call to TestReferenceLib.TestReferenceLibrary through the compiler? 您如何通过编译器将该调用推送到TestReferenceLib.TestReferenceLibrary Is there an interface somewhere you're not showing? 您未显示的地方是否有界面?

That aside, The MSDN documentation on Resolving Assembly Loads says that AssemblyResolve is only called when you try to load an assembly by name. 除此之外,有关解析程序集加载的MSDN文档指出,仅当您尝试按名称加载程序集时才调用AssemblyResolve

You're not doing that anywhere, so it sounds like you need an AppDomain.Load() , AppDomain.CreateInstance() or similar before your call to TestReferenceLib 您没有在任何地方进行此操作,因此听起来像在调用TestReferenceLib之前需要AppDomain.Load()AppDomain.CreateInstance()或类似的TestReferenceLib

I found a satisfying solution, so here it is if anybody else hits the wall. 我找到了一个令人满意的解决方案,所以如果有人撞墙,就在这里。

If you are compiling code dynamically - code that requires referenced class libraries which in turn are supposed to be embedded as resources into your assembly, make sure to disable GenerateInMemory and to NOT execute the file immediately via Invoking. 如果要动态编译代码-需要引用类库的代码,这些类库又应作为资源嵌入到程序集中,请确保禁用GenerateInMemory并不要通过调用立即执行文件。

If you want (like me) to compile an assembly then execute it immediately, generate it to a file, create an AppDomain and execute it inside of it as seen here: 如果要(像我一样)编译一个程序集,然后立即执行它,将其生成为一个文件,创建一个AppDomain并在其中执行它,如下所示:

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

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

domain.ExecuteAssembly(assembly.Location);

Here's the compiler params: 这是编译器参数:

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