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

时间:2018-12-23 21:28:45

标签: c#

下午好,

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

标有“ Pops errors”注释的行显示:

  

FileNotFoundException:无法加载文件或程序集   'TestReferenceLib,版本= 1.0.0.0,文化=中性,   PublicKeyToken = null”或其依赖项之一。系统无法   找到指定的文件。

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

通过“使用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);
}

2 个答案:

答案 0 :(得分:0)

您如何通过编译器将该调用推向class MyModel extends Model { public function __call($method, $parameters = null) { if ($method == 'create') { $create = parent::create($parameters[0]); if (!$created) { throw new \App\Exceptions\EloquentException; } return $created; } } } ?您未显示的地方有界面吗?

此外,Resolving Assembly Loads上的MSDN文档说TestReferenceLib.TestReferenceLibrary仅在您尝试按名称加载程序集时被调用。

您没有在任何地方进行此操作,因此听起来您需要AppDomain.Load()AppDomain.CreateInstance()或类似内容才能调用AssemblyResolve

答案 1 :(得分:0)

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

如果您正在动态编译代码-需要引用类库的代码,这些类库又应作为资源嵌入到程序集中,请确保禁用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;