我正在尝试制作一个小型C#工具来比较两个svn版本构建并跟踪任何类中的属性更改。我的目标是使用反射来比较我的dll的每个类的属性,而不使用Momo.Cecil。
通过实验,然后阅读本文Assembly Loading以及在Google上找到的一些主题,我了解到如果我们不使用Assembly.ReflectionOnlyLoadFrom
,那么具有相同身份的两个DLL将被解析为相同。
尝试使用他们的代码为每次加载创建一个AppDomain,并尝试从搜索中获得许多变体,我得到了这个例外,我找不到解释如何解决这个问题的任何线程:
API限制:程序集'文件:/// 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;
}
答案 0 :(得分:1)
这可以通过在单独的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
}
}