我确定我的问题的根本原因是类似的问题:
How do I pass references as method parameters across AppDomains?
,特别是this answer,但我不太确定如何修复它。
我遇到的问题是,我有一个我正在编写的Visual Studio扩展,它需要做的一件事就是将一个程序集加载到一个单独的域中(所以我可以把它转储到我的'完成它)并用它做一些事情。所以我的域名设置如下:
// The actual ApplicationBase of the current domain will be the one of VS and not of my plugin
// We need our new AppDomain to be able to find our assemblies
var p = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var setup = new AppDomainSetup()
{
ApplicationBase = p
};
domain = AppDomain.CreateDomain("MyTest_AppDomain", AppDomain.CurrentDomain.Evidence, setup);
var t = typeof(Proxy);
proxy = domain.CreateInstanceAndUnwrap(t.Assembly.FullName,
t.FullName,
false,
BindingFlags.Default,
null,
new object[] { assemblyPath },
null,
null) as Proxy;
我需要设置ApplicationBase
才能加载我的类Proxy
,即使它与上面的代码在同一个程序集中定义。没有它,我得到FileNotFoundExceptions
现在我的Proxy
课程看起来像这样:
public class Proxy : MarshalByRefObject
{
private Assembly _assembly;
private IEnumerable<Type> _types;
public IEnumerable<Type> Types
{
get
{
if (_types == null && _assembly != null)
{
_spiders = _assembly.GetTypes().Where(t => typeof(IFoo).IsAssignableFrom(t)).ToList();
}
return _types;
}
}
public Proxy(string assemblyPath)
{
_assembly = Assembly.LoadFile(assemblyPath);
}
public IFoo GetInstanceOf(string fooType)
{
var type = Types.FirstOrDefault(t => t.FullName == fooType);
if (type == null)
{
throw new InvalidOperationException($"Unknown type {fooType} in assembly {_assembly.FullName}");
}
return GetInstanceOf(type);
}
private IFoo GetInstanceOf(Type fooType)
{
var obj = Activator.CreateInstance(fooType);
return obj as IFoo;
}
public override object InitializeLifetimeService()
{
return null;
}
}
回到创建新AppDomain
的同一个班级和新Proxy
中AppDomain
的实例我有类似这样的内容:
public IFoo GetInstanceOf(Type type)
{
var name = type.FullName;
var foo = proxy.GetInstanceOf(name);
return foo;
}
最初我试图直接调用proxy.GetInstanceOf
传递类型,但这可能不起作用,原因与我的代码不起作用的原因相同。当我到达var foo = proxy.GetInstanceOf...
行时,我会收到一条ArgumentException
,其中包含以下消息:
对象类型无法转换为目标类型。
我认为问题是因为IFoo
中的MyTest_AppDomain
与IFoo
中的DefaultDomain
不一致IFoo
,但我不确定解决这个问题的正确方法是。
可能相关的是MyTest_AppDomain
本身是在单独的第三个程序集中定义的,我的VSIX项目和我尝试在单独域中加载的程序集都在引用。我想,我需要说服IFoo
从与DefaultDomain
相同的位置加载相同的IFoo
程序集,或者说服它们是同一个。
注意:我实现FooBase
的所有类都继承自一个自己继承自MarshalByRefObject
的抽象基础_assembly = Assembly.LoadFile(assemblyPath);
。
编辑更多地考虑这个问题可能来自这里:
assemblyPath
ApplicationBase
foo.dll
的路径不同,该路径拥有自己的IFoo
版本(其中ApplicationBase
已定义)。也许它是从Proxy.GetInstanceOf
加载之前从那里加载的?在typeof(IFoo).Assembly.Location
我可以查看ApplicationBase
,它会给我foo.dll
中设置的预期路径,但我不认为我的程序集加载它时会从export PATH=${PATH}:${DTITK_ROOT}/bin:${DTITK_ROOT}/utilities:${DTITK_ROOT}/scripts
获取$images=image::findorFail($id);
那里。
答案 0 :(得分:1)
我为你准备了一份快速工作的样本。这就是你所期望的,IFoo由参考调用者编组。
using System;
using System.Reflection;
namespace AppdomainTesting
{
class Program
{
static void Main(string[] args)
{
var p = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var setup = new AppDomainSetup()
{
ApplicationBase = p
};
IProxy proxy;
var domain = AppDomain.CreateDomain("MyTest_AppDomain", AppDomain.CurrentDomain.Evidence, setup);
var t = typeof(Proxy);
proxy = domain.CreateInstanceAndUnwrap(t.Assembly.FullName,
t.FullName,
false,
BindingFlags.Default,
null,
null,
null,
null) as IProxy;
// works
var typeofFoo = typeof(Foo);
var foo = proxy.GetFoo(new TypeDef() { Asembly = typeofFoo.Assembly.FullName, FullTypeName = typeofFoo.FullName });
Console.WriteLine(foo.Domain);
// Type also implements Serializable attribute (my mistake, I thought it did not)
foo = proxy.GetFoo(typeofFoo);
Console.WriteLine(foo.Domain);
Console.WriteLine();
Console.WriteLine("ENTER to exit");
Console.ReadLine();
}
}
public interface IFoo
{
string Domain { get; }
}
public class Foo : MarshalByRefObject, IFoo
{
public string Domain
{
get { return System.AppDomain.CurrentDomain.FriendlyName; }
}
}
public interface IProxy
{
IFoo GetFoo(TypeDef typeToGet);
IFoo GetFoo(Type type);
}
[Serializable]
public class TypeDef
{
public string Asembly { get; set; }
public string FullTypeName { get; set; }
}
public class Proxy : MarshalByRefObject, IProxy
{
public IFoo GetFoo(TypeDef typeToGet)
{
var type = Type.GetType(typeToGet.FullTypeName + ", " + typeToGet.Asembly, true);
var instance = Activator.CreateInstance(type) as IFoo;
return instance;
}
public IFoo GetFoo(Type type)
{
var instance = Activator.CreateInstance(type) as IFoo;
return instance;
}
}
}