我已经创建了一个测试库
public class Test
{
public int Add(int val1, int val2)
{
return val1 + val2;
}
}
一个叫它的项目:
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));
}
}
}
请帮忙找出我做错了什么?为什么我的装配被锁定了?
带有硬编码程序集名称的编辑:
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");
}
}
}
有趣的是,缓存的声明也被锁定了。
编辑2:
以下是阻止程序集的代码行
Console.WriteLine(obj.Add(1, 7));
因此,一旦访问了Lib.Test中的一个方法,就会阻塞它。
可以解决什么问题?
答案 0 :(得分:1)
当您运行锁定文件的Assembly.LoadFile()
时,您正在将程序集加载到主AppDomain中。如果要将其直接加载到AppDomain中,则需要直接使用AppDomain.Load()
,允许AppDomain根据您指定的参数解析它。请注意,由于程序集未在主AppDomain中加载,因此Main方法无法访问该类型。您的Lib.Test需要派生自MarshalByRefObject
,以便编组系统可以创建代理(当您将其分配给动态代理时,代理将进一步包装到动态代理中。)
编辑:
进一步想到,我怀疑这里的问题是,为了在动态代理上调用方法,它必须反映对象(它本身是你的其他AppDomain中实例的透明代理。)如果它最终会反映原始的类类型(而不是'隐藏'透明代理类型),这将导致它在本地AppDomain中加载程序集的副本(从而将其锁定。)这是使用时的一个原因AppDomain隔离,您通常将对象强制转换为在“主”应用程序和托管AppDomain都可以引用的单独程序集中定义的接口。他们将各自获得自己的接口程序集副本,但现在“实现”程序集已被隔离。
答案 1 :(得分:0)
您有两个选项,您需要在运行时查找程序集名称并对其进行硬编码,或者如果您不知道之前的运行时间,则需要编写第二个库,您知道{{ 1}}并在AppDomain中加载它。第二个库将是一个具有一个功能的类
FullName
这应该在没有锁定它的情况下将目标加载到新的AppDomain中,因为应该使用卷影副本打开它。
编辑:至于为什么你的方法不起作用,你在哪里加载锁定它once a assembly is loaded in to a AppDomain it can not be unloaded.