簡體   English   中英

程序集反射加載和應用程序域沖突

[英]Assembly reflection loading and app domain conflict

我正在嘗試制作一個小的C#工具來比較兩個svn修訂版本並跟蹤任何類中的屬性更改。 我的目標是在不使用Momo.Cecil的情況下使用反射來比較dll中每個類的屬性。

通過試驗,然后閱讀這篇文章Assembly Loading和在Google上找到的一些線程,我了解到,如果不使用Assembly.ReflectionOnlyLoadFrom則具有相同標識的兩個DLL將被解析為相同的。

嘗試使用他們的代碼為每次加載創建一個AppDomain,並嘗試搜索中的許多變體,但出現此異常,找不到任何線程來說明如何解決此問題:

API限制:程序集“ file:/// D:\\ somepath \\ 82 \\ MyLib.dll”已從其他位置加載。 無法從同一appdomain中的新位置加載該文件。

此錯誤在第二行的第二行(路徑82)上發生:

Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);

也許我不了解一些非常基本的知識,這些知識使我無法正確創建新的AppDomain?

這是用於重現此問題的所有代碼。

從我的入口點開始的代碼

        //Let say one of the property has been renamed between both commits
        var svnRev81Assembly = ReflectionOnlyLoadFrom(@"D:\somepath\81\MyLib.dll");
        var svnRev82Assembly = ReflectionOnlyLoadFrom(@"D:\somepath\82\MyLib.dll");

加載程序的實現

    private string _CurrentAssemblyKey;
    private Assembly ReflectionOnlyLoadFrom(string assemblyPath)
    {
        var path = Path.GetDirectoryName(assemblyPath);

        // Create application domain setup information.
        AppDomainSetup domaininfo = new AppDomainSetup();
        domaininfo.ApplicationBase = path;
        domaininfo.PrivateBinPath = path;

        _CurrentAssemblyKey = Guid.NewGuid().ToString();
        AppDomain currentAd = AppDomain.CreateDomain(_CurrentAssemblyKey, null, domaininfo); //Everytime we create a new domain with a new name        
        //currentAd.ReflectionOnlyAssemblyResolve += CustomReflectionOnlyResolver; This doesnt work anymore since I added AppDomainSetup        
        currentAd.SetData(_CurrentAssemblyKey, path);

        //Loading to specific location -  folder 81 or 82
        Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);

        //Preloading the 
        foreach (var assemblyName in assembly.GetReferencedAssemblies())
        {
            Assembly.ReflectionOnlyLoadFrom(Path.Combine(path, assemblyName.Name + ".dll"));
        }
        Type[] types = assembly.GetTypes();

        // Lastly, reset the ALS entry and remove our handler
        currentAd.SetData(_CurrentAssemblyKey, null);
        //currentAd.ReflectionOnlyAssemblyResolve -= CustomReflectionOnlyResolver; This doesnt work anymore since I added AppDomainSetup  

        return assembly;
    }

這可以通過在單獨的appdomain中加載dll來解決。

private static void ReflectionOnlyLoadFrom()
{
    var appDomain = AppDomain.CreateDomain("Temporary");
    var loader1 = (Loader)appDomain.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
    loader1.Execute(@"D:\somepath\81\MyLib.dll");
    var loader2 = (Loader)appDomain.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
    loader2.Execute(@"D:\somepath\82\MyLib.dll");
    loader1.CompareTwoDLLs(loader2);

    AppDomain.Unload(appDomain);
}

Loader.cs

public class Loader : MarshalByRefObject
{
    public Assembly TempAssembly { get; set; }
    public string Execute(string dllPath)
    {
        TempAssembly = Assembly.LoadFile(dllPath);
        return TempAssembly.FullName;
    }
    public void GetRefAssemblyTypes()
    {
        foreach (var refAssembly in TempAssembly.GetReferencedAssemblies())
        {
            var asm = Assembly.Load(refAssembly);
            var asmTypes = asm.GetTypes();
        }
    }
    public void CompareTwoDLLs(Loader l2)
    {
        var types1 = TempAssembly.GetTypes();
        var types2= l2.TempAssembly.GetTypes();
        GetRefAssemblyTypes();
        //logic to return comparison result
    }
 }

暫無
暫無

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

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