问题
I understand loaded assembly can not be unloaded directly so I created temporary domain and loaded assembly but I got error in creating shadow files.
The code I wrote is as follows:
[LoaderOptimization(LoaderOptimization.MultiDomainHost)]
[STAThread]
static void Main(string[] args)
{
string startupPath = @"D:\Temp\MyLib\bin\Debug";
string cachePath = Path.Combine(startupPath, "__cache");
string assembly = Path.Combine(startupPath, "MyLib.dll");
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = "MyLIb";
setup.ShadowCopyFiles = "true";
setup.CachePath = cachePath;
AppDomain domain = AppDomain.CreateDomain("MyLIb", AppDomain.CurrentDomain.Evidence, setup);
var np = FindFileInPath("MyLib.dll", cachePath);
var ass = Assembly.LoadFile(np);
var types = ass.GetTypes();
AppDomain.Unload(domain);
}
I got error in finding file in path "could not find a part of the path 'D:\Temp\MyLib\bin\Debug__cache'."
public static string FindFileInPath(string filename, string path)
{
filename = filename.ToLower();
foreach (var fullFile in Directory.GetFiles(path))
{
var file = Path.GetFileName(fullFile).ToLower();
if (file == filename)
return fullFile;
}
foreach (var dir in Directory.GetDirectories(path))
{
var file = FindFileInPath(filename, dir);
if (!string.IsNullOrEmpty(file))
return file;
}
return null;
}
}
Could someone help me out of this trouble.
Thanks in advance. Joon
回答1:
To start a new appdomain you need to set the ApplicationBase property of your AppDomainSetup. This is the path of the dll's you want to load. Also, you need to set the ShadowCopyDirectories property of your AppDomainSetup object. This will make a shadow copy of all the dll's that are in the given directories.The CachePath determines where the shadowfolders will be created.
For more information see: AppDomainSetup met property ShadowCopyDirectories
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = "MyLIb";
setup.ApplicationBase = dllsDir;
setup.ShadowCopyFiles = "true";
setup.CachePath = cachePath;
setup.ShadowCopyDirectories = dllsDir;
AppDomain = AppDomain.CreateDomain("MyAppDomain", null, setup);
You first need to invoke the CreateInstanceAndUnwrap
method of the new appdomain. Then you can begin loading dll's in the new Appdomain.
var proxy = AppDomain.CreateInstanceAndUnwrap(GetType().Assembly.GetName().ToString(), typeof(Proxy).FullName);
var assembly = proxy.GetAssembly(fullPathToDllInDllsDir);
This is the "Proxy" class you can create. Note that the most important part of this class is the MarshalByRefObject
public class Proxy : MarshalByRefObject
{
public Assembly GetAssembly(string assemblyPath)
{
try
{
return Assembly.Load(AssemblyName.GetAssemblyName(assemblyPath));
}
catch (Exception)
{
return null;
}
}
}
This will create a shadowfolder for that dll and load it in the appdomain (If ShadowCopyFiles is set to true)
Extra: Try to use the Assembly.Load() or Assembly.LoadFrom() methods and try to avoid the use of Assembly.LoadFile(). This is only needed in very specific cases. See this explanation
For assemblies that are loaded without context, the problem can be caused by using the Assembly.LoadFile method to load the same assembly from different paths. The runtime considers two assemblies that are loaded from different paths to be different assemblies, even if their identities are the same.
Note that you can use the Assembly.LoadFrom method to load these assemblies. Because they are now in the probing path, they will be loaded into the default load context instead of the load-from context. However, we recommend that you switch to the Assembly.Load method and supply full assembly display names to ensure that correct versions are always used.
来源:https://stackoverflow.com/questions/46067782/appdomain-doesnt-make-shadow-files