3

在 C# 中,如果外部 dll 不在应用程序目录中,则有 ResolveEventHandler 事件来加载它们。

要在 winform 应用程序中使用它,我在 Program.cs Main() 函数中注册事件,如下所示:

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);

然后是每次触发事件时都会调用的 ResolveAssembly 函数:

    static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
    {
        //MessageBox.Show(String.Format("Assembly {0} is missing", args.Name));


        //This handler is called only when the common language runtime tries to bind to the assembly and fails.

        //Retrieve the list of referenced assemblies in an array of AssemblyName.
        Assembly MyAssembly, objExecutingAssemblies;
        string strTempAssmbPath = "";
        string AssemblyName = new AssemblyName(args.Name).Name;

        objExecutingAssemblies = Assembly.GetExecutingAssembly();
        AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();

        //Loop through the array of referenced assembly names.
        foreach (AssemblyName strAssmbName in arrReferencedAssmbNames)
        {
            //Check for the assembly names that have raised the "AssemblyResolve" event.
            if (strAssmbName.Name == AssemblyName)
            {
                //Build the path of the assembly from where it has to be loaded.                
                strTempAssmbPath = @"C:\PowerVision\libraries\" + AssemblyName + ".dll";
                break;
            }

        }
        //Load the assembly from the specified path.                    
        MyAssembly = Assembly.LoadFrom(strTempAssmbPath);

        //Return the loaded assembly.
        return MyAssembly;
    }

问题是如何在/从类库中添加/调用此事件?

我有一个类库(DLL),它有 3 个对外部 DLL 的引用。我不想将这些 dll 复制到应用程序目录中,也不想将它们放入应用程序的子目录中。这些 DLL 应保留在特定的外部文件夹中(因此使用事件)。

问题是我不知道在 DLL(类库)中将这个事件注册放在哪里:

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
4

1 回答 1

1

You just need to put the event registration in your DLL in a place that gets called sometime BEFORE any of your 3 external DLLs get referenced.

A constructor of an object in your top DLL would be the first place to look. However, if that object is a sub-type of an object that is in one of those 3 external DLLs, then you may need to create a parent object for that object, and call the parent object first, and add the event registration in that parent's constructor.

E.g. if your DLL is a UserControl that is based on another UserControl that is in one of those 3 external DLL's, like this:

public partial class TopLevelUserControl: ExternalDllUserControl
{
    InitializeComponent();
}

then you may need to write code like this: Create a new user control called TopLevelUserControlLauncher, and place TopLevelUserControl in that userControl, docked. Then write code like this:

public partial class TopLevelUserControlLauncher: UserControl
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
    InitializeComponent(); // this will construct TopLevelUserControl
}
于 2013-07-15T03:15:36.210 回答