Ваш код выглядит так, как будто вы серьезно не понимаете, как взаимодействовать с отдельным доменом приложений.
Подумайте об общении с доменом приложений, как об общении с кем-то, кто в данный момент находится в другой стране. Вы знаете, где они, но вы не можете просто подойти и поговорить с ними. Если вы хотите, чтобы они что-то для вас сделали, вы должны открыть линию связи и сказать им, что вам нужно.
Способ, которым вы открываете эту линию связи, заключается в определении прокси-объекта, который можно создать внутри другого домена приложений, а затем пересечь границу обратно к вашему текущему домену приложений. Чтобы пересечь границу, необходимо, чтобы ваш объект был помечен как [Serializable]
или унаследован от MarshalByRefObject
. Поскольку на самом деле мы хотим поговорить со ссылкой в другом домене приложения , а не просто иметь ее копию, нам нужен прокси-сервер, чтобы сделать последнее.
private class CrossDomainQuery : MarshalByRefObject
{
public void LoadDataFromAssembly(string assemblyPath)
{
var assembly = Assembly.LoadFrom(assemblyPath);
//TODO: Do something with your assembly
}
}
В AppDomain существует метод CreateInstanceAndUnwrap (), который создаст экземпляр этого коммуникационного объекта внутри другого AppDomain , а затем вернет вам объект __TransparentProxy, который можно привести к типу прокси.
var crossDomainQuery = (CrossDomainQuery)adWireUp.CreateInstanceAndUnwrap(
typeof(CrossDomainQuery).Assembly.FullName,
typeof(CrossDomainQuery).FullName);
Если у вас есть этот прокси-объект, вы можете вызывать методы для него, и они будут вызываться в другом домене приложения.
crossDomainQuery.LoadDataFromAssembly(assemblyPath);
Так как это отличается от того, что делает ваш текущий пример кода?
Ваш текущий код на самом деле не выполняет ничего полезного внутри другого AppDomain.
adWireUp = AppDomain.CreateDomain(sFriendlyName, AppDomain.CurrentDomain.Evidence, ads);
asmReport = adWireUp.GetAssemblies()[0];
asmReport = Assembly.LoadFrom(sPath);
Это создает новый AppDomain, но затем он загружает все сборки из этого AppDomain в ваш текущий AppDomain. Кроме того, он явно загружает вашу сборку отчетов в ваш текущий AppDomain.
Создание домена приложения и вызов его методов не означает, что ваш код выполняется внутри него, так же как чтение о другой стране означает, что вы сейчас общаетесь с кем-то внутри него.
Даже если вы создаете прокси-объект и выполняете код внутри этого другого домена приложений, есть несколько вещей, о которых следует знать.
1) Оба AppDomains должны иметь возможность видеть тип, используемый для прокси-сервера, и вам может потребоваться обработать события AssemblyResolve для любого AppDomain вручную (хотя бы временно), чтобы помочь разрешить это.
2) Создание доменов приложений довольно дорого. Как правило, они не используются в ситуациях, когда вам нужно действительно быстро что-то раскрутить, предпринять какие-то действия и исчезнуть. Вы должны планировать либо держать их как можно дольше, либо быть готовыми к снижению производительности при каждом вызове.
3) Вы сказали, что тип создаваемого вами отчета не сериализуем, и возможность сериализации объекта является требованием для передачи этого типа обратно из другого домена приложения. Можно определить сериализуемый класс, который может передавать соответствующие данные через границу, и использовать его для передачи данных отчета, но вам придется определить, подходит ли это для вашей конкретной ситуации.
Кроме того, кроме случаев, когда у вас нет логики, которая зависит от переменных, для которых задано значение null, установка значения null в вашем файле finally ничего не даст и не усложнит ваш код.