我试图在另一个应用程序域中通过工厂方法创建Class的实例有没有解决这个问题的方法? 编辑: 问题是如何做到这一点
谢谢。
答案 0 :(得分:2)
有一些方法可以解决这个问题。根据您希望解决方案的扩展程度和解决方案的复杂程度,您可能需要查看MAF(请参阅System.AddIn命名空间),因为它处理加载AddIns并且已经支持AppDomain分离。它还实现了一整套功能,可以对AppDomains中创建的对象进行生命周期管理,并加载/卸载AddIns和版本控制。
如果您希望实现自己的,或者只是想要更多地了解AppDomain,那么这里有一个希望有用的示例。它对AppDomain设置,安全性或生命周期管理没有任何作用,并且使代码更紧凑,没有错误处理,但它可以用作指南。
如果您从一个使用工厂创建Person对象的示例开始:
public class Person
{
internal Person(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class PersonFactory
{
public static Person CreatePerson(string name)
{
return new Person(name);
}
}
class Program
{
static void Main(string[] args)
{
Person p = PersonFactory.CreatePerson("John Smith");
}
}
然后,您可以添加到此处以在另一个AppDomain中创建一个Person,并对上面的代码进行一些相当简单的更改。
修改后的代码是:
public class Person : MarshalByRefObject
{
internal Person(string name)
{
Name = name;
}
public string Name { get; private set; }
public string AppDomainName { get { return AppDomain.CurrentDomain.FriendlyName; } }
}
public class PersonFactory
{
public static Person CreatePerson(string name)
{
return new Person(name);
}
public static Person CreatePersonInAppDomain(string name, AppDomain domain)
{
return (Person)domain.CreateInstanceAndUnwrap(
typeof(Person).Assembly.FullName,
typeof(Person).FullName,
false,
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { name },
null,
null
);
}
}
class Program
{
static void Main(string[] args)
{
AppDomain domain = AppDomain.CreateDomain("NewDomain");
Person person1 = PersonFactory.CreatePerson("John Smith");
Person person2 = PersonFactory.CreatePersonInAppDomain("Jane Smith", domain);
Console.WriteLine("Person: Name={0}, Domain={1}", person1.Name, person1.AppDomainName);
Console.WriteLine("Person: Name={0}, Domain={1}", person2.Name, person2.AppDomainName);
}
}
输出应为:
Person: Name=John Smith, AppDomain=[your exe name] Person: Name=Jane Smith, AppDomain=NewDomain
那么,发生了什么?
由于person2是另一个AppDomain中的对象,因此它需要是Serializable或派生自MarshalByRefObject。在这个例子中,我派生自MarshalByRefObject,因此真实实例仅存在于第二个AppDomain中,原始AppDomain中的引用实际上是一个代理。如果我选择了Serializable实现,那么该人的副本将被传递回原始的AppDomain。
这是需要考虑的其他因素,因为每次调用新的AppDomain时,需要对任何参数进行编组,这会对性能产生一些影响。此外,还需要考虑对象的生命周期,因为MarshalByRefObjects最终会超时并被垃圾收集器收集。您需要调查生命周期管理以进一步扩展这一点。