I use load / unload assembly to get all types then create instances from that type. I debug, the variable "result" in the Reflect method of the AssemblyReflectionProxy class has a value but after the return line of that method is an error, hope everyone help me, I want to copy some values in the instance created from the type of the assembly that I have loaded.
Error Infomation
"Could not load file or assembly 'BeyConsRevitProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
StackTrace
" at BeyConsConsole.Reflections.AssemblyReflectionProxy.Reflect[TResult](Func2 func) in D:\Github\BeyConsPlugin\BeyConsConsole\Reflections\AssemblyReflectionProxy.cs:line 39\r\n at BeyConsConsole.Reflections.AssemblyReflectionManager.Reflect[TResult](String assemblyPath, Func
2 func) in D:\Github\BeyConsPlugin\BeyConsConsole\Reflections\AssemblyReflectionManager.cs:line 59\r\n at BeyConsConsole.Program.Main() in D:\Github\BeyConsPlugin\BeyConsConsole\Program.cs:line 27"
Error Image
[https://ift.tt/3n0r4Ow]
[https://ift.tt/38osmPw]
[https://ift.tt/36aB0ya]
IAssemblyReflectionProxy interface
public interface IAssemblyReflectionProxy
{
void LoadAssembly(string assemblyPath);
TResult Reflect<TResult>(Func<Assembly, TResult> func);
}
AssemblyReflectionProxy class
public class AssemblyReflectionProxy : MarshalByRefObject, IAssemblyReflectionProxy
{
#region Fields
private string assemblyPath;
#endregion
#region Methods
public void LoadAssembly(string assemblyPath)
{
try
{
this.assemblyPath = assemblyPath;
Assembly.ReflectionOnlyLoadFrom(assemblyPath);
}
catch { }
}
public TResult Reflect<TResult>(Func<Assembly, TResult> func)
{
DirectoryInfo directory = new FileInfo(assemblyPath).Directory;
Assembly ResolveEventHandler(object s, ResolveEventArgs e) { return OnReflectionOnlyResolve(e, directory); }
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveEventHandler;
Assembly assembly = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().FirstOrDefault(a => a.Location.CompareTo(assemblyPath) == 0);
TResult result = func(assembly);
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= ResolveEventHandler;
return result;
}
private Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)
{
Assembly loadedAssembly = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().FirstOrDefault(asm => string.Equals(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase));
if (null != loadedAssembly) return loadedAssembly;
AssemblyName assemblyName = new AssemblyName(args.Name);
string dependentAssemblyFilename = Path.Combine(directory.FullName, assemblyName.Name + ".dll");
if (File.Exists(dependentAssemblyFilename))
{
return Assembly.ReflectionOnlyLoadFrom(dependentAssemblyFilename);
}
return Assembly.ReflectionOnlyLoad(args.Name);
}
#endregion
}
AssemblyReflectionManager class
public class AssemblyReflectionManager : IDisposable
{
#region Fields
private readonly Dictionary<string, AppDomain> mapDomains = new Dictionary<string, AppDomain>();
private readonly Dictionary<string, AppDomain> loadedAssemblies = new Dictionary<string, AppDomain>();
private readonly Dictionary<string, AssemblyReflectionProxy> proxies = new Dictionary<string, AssemblyReflectionProxy>();
#endregion
#region Methods
public bool LoadAssembly(string assemblyPath, string domainName)
{
if (!File.Exists(assemblyPath)) return false;
if (loadedAssemblies.ContainsKey(assemblyPath)) return false;
AppDomain appDomain;
if (mapDomains.ContainsKey(domainName))
{
appDomain = mapDomains[domainName];
}
else
{
appDomain = CreateChildDomain(AppDomain.CurrentDomain, domainName);
mapDomains[domainName] = appDomain;
}
try
{
Type proxyType = typeof(AssemblyReflectionProxy);
if (null != proxyType.Assembly)
{
var proxy = (AssemblyReflectionProxy)appDomain.CreateInstanceFrom(proxyType.Assembly.Location, proxyType.FullName).Unwrap();
proxy.LoadAssembly(assemblyPath);
loadedAssemblies[assemblyPath] = appDomain;
proxies[assemblyPath] = proxy;
return true;
}
}
catch { }
return false;
}
public TResult Reflect<TResult>(string assemblyPath, Func<Assembly, TResult> func)
{
if (loadedAssemblies.ContainsKey(assemblyPath) && proxies.ContainsKey(assemblyPath))
{
return proxies[assemblyPath].Reflect(func);
}
return default;
}
public bool UnloadAssembly(string assemblyPath)
{
if (!File.Exists(assemblyPath)) return false;
if (loadedAssemblies.ContainsKey(assemblyPath) && proxies.ContainsKey(assemblyPath))
{
AppDomain appDomain = loadedAssemblies[assemblyPath];
int count = loadedAssemblies.Values.Count(a => a == appDomain);
if (count != 1) return false;
try
{
mapDomains.Remove(appDomain.FriendlyName);
AppDomain.Unload(appDomain);
loadedAssemblies.Remove(assemblyPath);
proxies.Remove(assemblyPath);
return true;
}
catch { }
}
return false;
}
public bool UnloadDomain(string domainName)
{
if (string.IsNullOrEmpty(domainName)) return false;
if (mapDomains.ContainsKey(domainName))
{
try
{
var appDomain = mapDomains[domainName];
var assemblies = new List<string>();
foreach (var kvp in loadedAssemblies)
{
if (kvp.Value == appDomain) assemblies.Add(kvp.Key);
}
foreach (var assemblyName in assemblies)
{
loadedAssemblies.Remove(assemblyName);
proxies.Remove(assemblyName);
}
mapDomains.Remove(domainName);
AppDomain.Unload(appDomain);
return true;
}
catch { }
}
return false;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~AssemblyReflectionManager()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
foreach (var appDomain in mapDomains.Values)
{
AppDomain.Unload(appDomain);
}
loadedAssemblies.Clear();
proxies.Clear();
mapDomains.Clear();
}
}
private AppDomain CreateChildDomain(AppDomain parentDomain, string domainName)
{
Evidence evidence = new Evidence(parentDomain.Evidence);
AppDomainSetup setup = parentDomain.SetupInformation;
return AppDomain.CreateDomain(domainName, evidence, setup);
}
#endregion
}
Test
public class Program
{
public static void Main()
{
try
{
string assemblyPath = @"D:\Github\BeyConsPlugin\BeyConsProject\bin\x64\Debug\BeyConsRevitProject.dll";
AssemblyReflectionManager manager = new AssemblyReflectionManager();
if (manager.LoadAssembly(assemblyPath, Guid.NewGuid().ToString()))
{
var result = manager.Reflect(assemblyPath, (a) =>
{
Type[] types = new Type[] { };
types = a.GetTypes();
return types;
});
}
}
catch (Exception exception)
{
string str = exception.ToString();
}
Console.ReadKey();
}
}
Debug before line 39 still gets types, after line 39, throw an exception
[4] https://i.stack.imgur.com/CgyEQ.png
Aucun commentaire:
Enregistrer un commentaire