AppDomain不会制作影子文件

时间:2017-09-06 05:56:55

标签: c# .net appdomain

我理解加载的程序集不能直接卸载所以我创建了临时域并加载了程序集但是我在创建影子文件时遇到错误。

我写的代码如下:

[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);
    }

我在路径中找到文件时遇到错误"找不到路径的一部分' 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;
    }
  }

有人可以帮助我解决这个问题。

提前致谢。 俊

1 个答案:

答案 0 :(得分:0)

要启动新的appdomain,您需要设置AppDomainSetup的ApplicationBase属性。这是您要加载的dll的路径。此外,您需要设置AppDomainSetup对象的ShadowCopyDirectories属性。这将生成给定目录中所有dll的卷影副本.CachePath确定将在何处创建shadowfolders。

有关详细信息,请参阅:AppDomainSetup符合财产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);

首先需要调用新appdomain的CreateInstanceAndUnwrap方法。然后,您可以开始在新的Appdomain中加载dll。

var proxy = AppDomain.CreateInstanceAndUnwrap(GetType().Assembly.GetName().ToString(), typeof(Proxy).FullName);
var assembly = proxy.GetAssembly(fullPathToDllInDllsDir);

这是"代理"你可以创建的课程。请注意,此类最重要的部分是MarshalByRefObject

 public class Proxy : MarshalByRefObject
 {
        public Assembly GetAssembly(string assemblyPath)
        {
            try
            {
                return Assembly.Load(AssemblyName.GetAssemblyName(assemblyPath));
            }
            catch (Exception)
            {
                return null;
            }
        }   
} 

这将为该dll创建一个shadowfolder并将其加载到appdomain中(如果ShadowCopyFiles设置为true)

额外:尝试使用Assembly.Load()或Assembly.LoadFrom()方法并尝试避免使用Assembly.LoadFile()。只有在非常具体的情况下才需要这样做。 See this explanation

  

对于在没有上下文的情况下加载的程序集,使用Assembly.LoadFile方法从不同路径加载相同的程序集可能会导致此问题。运行时认为从不同路径加载的两个程序集是不同的程序集,即使它们的标识相同。

     

请注意,您可以使用Assembly.LoadFrom方法加载这些程序集。因为它们现在位于探测路径中,所以它们将被加载到默认的加载上下文而不是加载来自上下文。但是,我们建议您切换到Assembly.Load方法并提供完整的程序集显示名称,以确保始终使用正确的版本。