2015-10-07 4 views
0

Iam пытается использовать AppDomains, чтобы изолировать и запустить код в моем приложении. Что мне нужно сделать, это создать новый AppDomain для каждого клиента и под этим AppDomain, мне нужно создать экземпляр другого класса, который содержит код, который необходимо изолировать. Мне также нужно каким-то образом сохранить этот созданный экземпляр, чтобы я мог получить к нему доступ позже, когда тот же клиент, который создал его, снова вызывает. Путь Im создавая сейчас это:Хранение экземпляра объекта, созданного под AppDomain

private Dictionary<string, IsolatedClass> isolatedClassesList = new Dictionary<string, IsolatedClass>(); 

public void Initialize(string clientId) 
{ 
    AppDomain appDomain = AppDomain.CreateDomain("New AppDomain"); 

    IsolatedClass isolatedClass = (IsolatedClass)appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(IsolatedClass).FullName); 

    isolatedClass.Initialize(clientId); 

    isolatedClassesList.Add(clientId, isolatedClass); 
} 

Создание AppDomain и первый вызов «Initiliaze(clientId)» метод отлично работает. Также хранение его в словаре (для последующего использования) выполняется без каких-либо исключений.

Проблема возникает, когда я пытаюсь получить экземпляр ранее созданного IsolatedClass позже, как это:

public void DoSomething (string clientId) 
{ 
    IsolatedClass isolatedClass = isolatedClassesList.First(x => x.Key == clientId).Value; 

    isolatedClass.RunIsolatedMethod(); 
} 

Он бросает исключение нулевой референс (он не может получить экземпляр). Когда я помещаю точку останова и проверяю, что находится внутри словаря, для Value, это показывает мне, что: «Получение этого типа прозрачного прокси не поддерживается в этом контексте».

Это полностью неправильный подход или есть какая-то незначительная ошибка? Если мой подход совершенно не прав, есть ли другой способ, как достичь моей цели?


EDIT

Видимо, был какой-то вопрос с самим IsolatedClass - это был унаследовать от другого класса, который наследует от MarshallByRefObject. Когда я создал простой класс манекена и работал с инструкцией от Kentonbmax, он сработал. Я продолжу тестирование, чтобы увидеть, какова была настоящая проблема.

+0

Посмотрите на System.Runtime.Caching.MemoryCache. Вы можете поместить свой построенный объект в кеш, используя ключ кеша, который идентифицирует как домен приложения/клиентский запрос, так и объект. – StingyJack

ответ

1

Я пробовал это, и единственное различие заключается в том, что мой класс находится внутри другой библиотеки. Вы можете заменить IsolClass на MarshalByRefObject как ваш тип значения в словаре, если у вас есть разные типы классов, с которыми вы хотите взаимодействовать.

var domain = AppDomain.CreateDomain(typeof(MyType).Assembly.FullName); 

        var proxy = domain.CreateInstanceAndUnwrap(
         typeof(MyType).Assembly.FullName, 
         typeof(MyType).FullName) as MyType; 

UnhandledException и DomainUnload события внутри вашего IsolatedClass хороший способ избавиться от каких-либо ресурсов в вашем IsolatedClass при разгрузке ваших AppDomains. Кроме того, я рекомендую использовать «как» вместо прямого приведения, чтобы проверить, не удалось ли выполнить бросок, не выбрасывая InvalidCast Exception.

Использование .Первый проблематично, потому что вам не гарантировано, что ключ существует и, следовательно, может вернуть нулевую ссылку. Если вы знаете clientId, когда вы вызываете «Инициализировать», почему вы не знаете его, когда вызываете DoSomething?

if(_isolatedClassesList.ContainsKey(clientId) 
{ 
    MyType mine = _isolatedClassesList[clientId] as MyType; 
    mine.MyMethod(); 
} 
+0

Спасибо за ваш ответ. Я попытался переключить тип значения в словаре в MarshalByRefObject. Добавление в словарь по-прежнему отлично работает, но при попытке получить объект с помощью 'IsolClass isolatedClass = isolatedClassesList.First (x => x.Key == clientId) .Value как IsolClass;' он по-прежнему выбрасывает исключение null refference. Я продолжу тестирование MemoryCache, как было предложено StingyJack. – JakubJ

+0

См. Мое исправленное решение. – Kentonbmax

+0

Спасибо, но все равно.Причина, по которой мне нужно идентифицировать его clientId, заключается в том, что основным классом является класс сервиса WCF, и поэтому многие клиенты могут подключиться к нему. Дело в том, что я уверен, что ключ присутствует в словаре, я даже проверил его с помощью контрольных точек. Проблема заключается в том, что способ Im, хранящий экземпляр 'IsolatedClass' (или MarshalByRefObject, из которого наследуется мой класс), является, возможно, неправильным, потому что я не могу вернуть значение обратно. – JakubJ

Смежные вопросы