.NET引用来自其他位置的DLL

时间:2011-08-07 10:02:13

标签: c# .net dll

我正在根据第三方程序中包含的某些DLL制作程序。我不允许自己分发这些DLL。必须安装第三方程序才能使我的程序正常工作。

如何引用这些DLL?我通过程序设置的注册表项知道它们的确切位置。

我试图在Project-> References中添加文件并将CopyLocal设置为false但是当我启动i然后得到FileNotFoundException“无法加载文件或程序集”。

我曾尝试将事件添加到AppDomain.CurrentDomain.AssemblyResolve并在那里加载文件,但问题是我在程序启动之前得到了异常。即使我在第一行放置一个断点,也会在断点被触发之前抛出异常。

2 个答案:

答案 0 :(得分:9)

来自C# 3.0 in a Nutshell, 3rd edition, by Joseph and Ben Albahari,p。 557-558:

  

在基础文件夹外部署程序集

     

有时您可能会选择将程序集部署到应用程序基目录以外的其他位置 [...] 要使其工作,您必须协助CLR查找基础之外的程序集夹。最简单的解决方案是处理AssemblyResolve事件。

(我们可以忽略这样一个事实:在您的情况下,除了您之外的其他人正在部署程序集。)

你试过的。但是后来有一个非常重要的线索。阅读两个代码注释:

public static void Loader
{
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.AssemblyResolve += FindAssem;

        // We must switch to another class before attempting to use
        // any of the types in C:\ExtraAssemblies:
        Program.Go();
    }

    static Assembly FindAssem(object sender, ResolveEventArgs args)
    {
        string simpleName = new AssemblyName(args.Name).Name;
        string path = @"C:\ExtraAssemblies\" + simpleName + ".dll";

        if (!File.Exists(path)) return null;
        return Assembly.LoadFrom(path);
    }
}

public class Program
{
    public static void Go()
    {
        // Now we can reference types defined in C:\ExtraAssemblies
    }
}

如您所见,解析外部程序集的类不得引用任何外部DLL 任何地方的任何类型。如果是,则执行代码在AssemblyResolve有机会跑之前停下来。

答案 1 :(得分:4)

您的应用程序爆炸,因为JIT编译器是第一个需要加载程序集的程序。您需要小心避免在Main()方法中使用程序集中的类型。这并不难,只需编写另一个Main方法并给它一个属性,告诉抖动它永远不应该内联该方法。如果没有该属性,当优化程序内联该方法时,它仍可能在Release版本中炸弹。像这样:

using System;
using System.Runtime.CompilerServices;

class Program {
    static void Main(string[] args) {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        DelayedMain(args);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void DelayedMain(string[] args) {
        // etc..
    }


    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
        // etc...
    }
}

在您以这种方式提交之前,请与供应商联系并寻求建议。必须有一种更简单的方式来行使您的许可权利。 GAC是一个常见的选择,也许您只需要在您的开发机器上运行gacutil。