[英]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.