Создать экземпляр myClass методом фабрики в другом домене приложения - PullRequest
0 голосов
/ 09 июня 2011

Я пытаюсь создать экземпляр MyClass методом фабрики в другом домене приложения. Есть ли решение этой проблемы?Отредактировано: вопрос в том, как это сделать

Спасибо.

1 Ответ

2 голосов
/ 09 июня 2011

Есть несколько вариантов решения этой проблемы.В зависимости от того, как вы хотите масштабировать свое решение и насколько оно уже сложное, вы можете посмотреть на MAF (см. Пространство имен System.AddIn), поскольку это обрабатывает загрузку 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");
    }
}

Затем вы можете добавить к нему, чтобы создать Person в другом домене приложения с несколькими довольно простыми изменениями в приведенном выше коде.

Сделайте класс Person объектом MarshalByRefObject Добавьте еще одно свойство 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, то копия этого человека будет передана обратно в исходный домен приложений.

Это что-то еще, что необходимо учитывать при каждом вызове нового домена приложений, любые параметры должны бытьмаршаллировал, что будет иметь некоторое влияние на производительность.Кроме того, необходимо учитывать и время жизни объекта, так как MarshalByRefObjects будет в конечном итоге истекать и будет собираться сборщиком мусора.Вам нужно будет изучить управление жизненным циклом, чтобы продлить его.

...