簡體   English   中英

在不同的AppDomain中加載/卸載程序集

[英]Loading/Unloading assembly in different AppDomain

我需要在運行時加載的程序集中執行一個方法。 現在我想在方法調用后卸載那些已加載的程序集。 我知道我需要一個新的AppDomain,所以我可以卸載庫。 但在這里,出現了問題。

要加載的程序集是我的插件框架中的插件。 他們根本沒有切入點。 我所知道的是它們包含一些實現給定接口的類型。 舊的非AppDomain代碼看起來像這樣(稍微縮短):

try
{
    string path = Path.GetFullPath("C:\library.dll");
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    Assembly asm = Assembly.LoadFrom(path);
    Type[] types = asm.GetExportedTypes();
    foreach (Type t in types)
    {
        if ((t.GetInterface("IStarter") != null) && !t.IsAbstract)
        {
            object tempObj = Activator.CreateInstance(t);
            MethodInfo info = t.GetMethod("GetParameters");
            if (info != null)
            {
                return info.Invoke(tempObj, null) as string;
            }
        }
    }
}
catch (Exception ex)
{
    MessageBox.Show(String.Format("Damn '{0}'.", ex.Message), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    if (args.Name.StartsWith("MyProject.View,"))
    {
        string path = Path.GetFullPath("C:\view.dll"));
        return Assembly.LoadFrom(path);
    }
    return null;
}

現在我希望它們加載到自己的AppDomain中:

try
{
    string path = Path.GetFullPath("C:\library.dll");
    AppDomain domain = AppDomain.CreateDomain("TempDomain");
    domain.AssemblyResolve += CurrentDomain_AssemblyResolve;  // 1. Exception here!!
    domain.ExecuteAssembly(path);  // 2. Exception here!!
    domain.CreateInstanceFrom(...);  // 3. I have NO clue, how the type is named.
    domain.Load(...);  // 4. I have NO clue, how the assembly is named.
    domain.DoCallBack(...); // 5. Exception here!!
    // ...
}
catch (Exception ex)
{
    MessageBox.Show(String.Format("Damn '{0}'.", ex.Message), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

如你所見,我已經提出了5個案例。

  1. 如果我設置事件處理程序,我得到一個異常,無法找到/加載程序集(它是管理控制台(mmc.exe)SnapIn。

  2. ExecuteAssembly沒有找到入口點(好吧,沒有入口點)。

  3. 我不知道該類型是如何命名的。 如何通過接口加載?

  4. 類似於3.如何獲取程序集的名稱?

  5. 與1中的錯誤相同。

我認為問題可能是某種方式的管理控制台,或者我不知道我做錯了什么。 任何幫助表示贊賞。

更新1

我現在嘗試使用發布的代理解決方案。

AppDomain domain = AppDomain.CreateDomain("TempDomain");
InstanceProxy proxy = domain.CreateInstanceAndUnwrap(Assembly.GetAssembly(
    typeof(InstanceProxy)).FullName, typeof(InstanceProxy).ToString()) as InstanceProxy;
if (proxy != null)
{
    proxy.LoadAssembly(path);
}
AppDomain.Unload(domain);

public class InstanceProxy : MarshalByRefObject
{
    public void LoadAssembly(string path)
    {
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        Assembly asm = Assembly.LoadFrom(path);
        Type[] types = asm.GetExportedTypes();
        // ...see above...
    }
}

這也不起作用。 在嘗試創建代理對象時,我得到一個異常:

無法加載文件或程序集“MyProject.SnapIn,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null”或其依賴項之一。 該系統找不到指定的文件。

錯誤消息中的文件是加載到mmc(SnapIn)中的文件。 知道如何修復此錯誤嗎? 不調用AppDomain.AssemblyResolve(在舊域或新域中都不會)。

更新2

我現在嘗試使用AppDomainSetup的解決方案。 現在,異常已更改為:

無法加載文件或程序集'file:/// C:/Development/MyProject/bin/SnapIn/MyProject.SnapIn.DLL'或其依賴項之一。 給定的程序集名稱或代碼庫無效。 (HRESULT異常:0x80131047)

任何想法?

嘗試這個:

namespace SeperateAppDomainTest
{
    class Program
    {
        static void Main(string[] args)
        {
            LoadAssembly();
        }

        public static void LoadAssembly()
        {
            string pathToDll = Assembly.GetExecutingAssembly().CodeBase;
            AppDomainSetup domainSetup = new AppDomainSetup { PrivateBinPath = pathToDll };
            var newDomain = AppDomain.CreateDomain("FooBar", null, domainSetup);
            ProxyClass c = (ProxyClass)(newDomain.CreateInstanceFromAndUnwrap(pathToDll, typeof(ProxyClass).FullName));
            Console.WriteLine(c == null);

            Console.ReadKey(true);
        }
    }

    public class ProxyClass : MarshalByRefObject { }

請看一下之前的答案: 如何在Windows Mobile(.NET CF)上將程序集加載到不同的AppDomain中? 該答案創建了一個代理類,它運行到新的AppDomain上下文中,因此,您可以完全控制您的初始化。

您可以在ServiceApplicationProxy類中創建一個Start()方法,並使用proxy.Start()從您的主機中正常調用它。

https://msdn.microsoft.com/en-us/library/3c4f1xde%28v=vs.110%29.aspx

指定

typeName類型:System.String

 The fully qualified name of the requested type, including the namespace but not the assembly, as returned by the Type.FullName 

屬性。

因此嘗試使用完全限定名稱調用,而不是使用typeof(InstanceProxy).ToString()使用字符串/文本"<<Namespace>>.InstanceProxy"

如下

InstanceProxy proxy = domain.CreateInstanceAndUnwrap(path, "<<Namespace>>.InstanceProxy") as InstanceProxy;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM