阴影复制,以便不锁定程序集

NDe*_*per 6 .net c# clr

我创建了一个测试库

public class Test
{
    public int Add(int val1, int val2)
    {
        return val1 + val2;
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个项目叫它:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace Loader
{
    class Program
    {
        static void Main(string[] args)
        {
            String path = @"...Lib.dll"; // path to lib
            var name = Path.GetFileName(path);

            AppDomainSetup setup = new AppDomainSetup  
            {
                ApplicationBase = @"...", // directory where Lib.dll is 
                ShadowCopyFiles = "true",
                ShadowCopyDirectories = @"..."// directory where Lib.dll is 
            };  

            var appdomain = AppDomain.CreateDomain("Loader." + name, null, setup);
            Assembly ass = Assembly.LoadFile(path); // <--- I think here is the problem, here where assembly is locked
            Assembly assembly = appdomain.Load(ass.FullName);

            dynamic a = assembly.CreateInstance("Lib.Test");

            Console.WriteLine(a.Add(1, 5));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请帮忙找出我做错了什么?我的装配为何被锁定?

编辑:使用硬编码程序集名称:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace Loader
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomainSetup ads = new AppDomainSetup();

            String fullPath = @"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Lib.dll";

            ads.ShadowCopyFiles = "true";
            ads.ApplicationName = "AppName";
            ads.ShadowCopyDirectories = Path.GetDirectoryName(fullPath);
            //ads.ApplicationBase = Path.GetDirectoryName(fullPath);
            //ads.PrivateBinPath = Path.GetDirectoryName(fullPath);
            ads.CachePath = @"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Cache\";

            AppDomain ad = AppDomain.CreateDomain("myName" + ads.ApplicationName, null, ads);

            ad.AssemblyResolve += new ResolveEventHandler( ad_AssemblyResolve );

            Console.WriteLine(ad.ShadowCopyFiles);
            Console.WriteLine(ad.SetupInformation.ShadowCopyDirectories);

            try
            {
                //Assembly assembly = ad.Load(AssemblyName.GetAssemblyName(fullPath));
                //dynamic obj = ad.CreateInstanceAndUnwrap(assembly.GetName().Name, "Lib.Test");

                dynamic obj = ad.CreateInstanceAndUnwrap("Lib", "Lib.Test");

                Console.WriteLine(obj.Add(1, 7));

                Console.ReadKey();

                Console.WriteLine(obj.Add(1, 90));
            }
            catch( Exception e)
            {
                Console.WriteLine( e.Message );
            }
        }

        static Assembly ad_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            return Assembly.LoadFile(@"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Lib.dll");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有趣的是,缓存的声明也被锁定了.

编辑2:

这是阻止程序集的代码行

Console.WriteLine(obj.Add(1, 7));
Run Code Online (Sandbox Code Playgroud)

因此,一旦访问Lib.Test中的方法,就会阻止组合.

什么可以解决方案?

Sco*_*ain 0

您有两个选择,您需要在运行时之前查找程序集名称并将其硬编码,或者如果您不知道运行时之前,您需要编写第二个您知道的库并将其加载FullName到应用程序域。第二个库将是一个具有一个功能的类

public Assembly GetAssemblyForOtherAppDomain(string path) 
{ 
    return Assembly.LoadFile(path) 
}
Run Code Online (Sandbox Code Playgroud)

这应该将您的目标加载到新的 AppDomain 中,而不需要锁定它,因为应该使用卷影副本打开它。

编辑:至于为什么你的方法不起作用,你在加载锁定它的位置是正确的,一旦程序集加载到AppDomain中,它就无法卸载。