在另一个应用程序域中按工厂方法创建Class实例

时间:2011-06-09 11:39:22

标签: c# applicationdomain

我试图在另一个应用程序域中通过工厂方法创建Class的实例有没有解决这个问题的方法? 编辑: 问题是如何做到这一点

谢谢。

1 个答案:

答案 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,并对上面的代码进行一些相当简单的更改。

  • 使类Person成为MarshalByRefObject
  • 向Person输入另一个属性,输出他们的AppDomain进行测试
  • 向工厂添加另一个静态方法,以便在其他AppDomain中创建
  • 修改后的代码是:

    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最终会超时并被垃圾收集器收集。您需要调查生命周期管理以进一步扩展这一点。