B
If you're transferring an object from another dome, you're putting it in your dome, which you're about to avoid. Decisions may be given to primitive types. In order not to limit yourself to simple colombies, you need to use it. MarshalByRefObject (they are not copied between domains but performed in the house where they are created).Okay, here's the work code.It's a flame, DomainsPlugin.dll:namespace DomainsPlugin
{
public class Plugin
{
public IEnumerable<AssemblyName> GetNames()
{
return AppDomain.CurrentDomain.GetAssemblies().Select(asm => asm.GetName());
}
}
}
Nothing special, just a working method.Now main programme:namespace DomainsMain
{
class Program
{
static void Main(string[] args)
{
// в этом каталоге бежит программа
var executableDir = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
// это каталог, где лежит плагин.
// у вас он будет лежать, понятно, в другом месте
var pluginDir = Path.GetFullPath(Path.Combine(
executableDir, "..", "..", "..", "DomainsPlugin", "bin", "Debug"));
// оригинал плагина
var pluginSourceFile = Path.Combine(pluginDir, "DomainsPlugin.dll");
// а сюда мы его скопируем, и отсюда будем загружать
var pluginWorkingFile = Path.Combine(executableDir, "DomainsPlugin.dll");
// копируем
File.Copy(pluginSourceFile, pluginWorkingFile, overwrite: true);
// окей, теперь новый домен
var pluginDomain = AppDomain.CreateDomain("Plugin");
// теперь, создаём экземпляр нашего класса в новом домене
// у нас на него реально лишь прокси-объект
var resident = (Resident)pluginDomain.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName,
"DomainsMain.Resident");
// получили данные
resident.Obtain();
// выводим их
foreach (var r in resident.Result)
Console.WriteLine(r.ToString());
// выгружаем домен...
AppDomain.Unload(pluginDomain);
// ... и удаляем плагин
File.Delete(pluginWorkingFile);
}
}
// простой класс, будет выполняться в другом домене
public class Resident : MarshalByRefObject
{
public List<AssemblyName> Result;
public void Obtain()
{
// загружаем библиотеку
var asm = Assembly.LoadFrom("DomainsPlugin.dll");
var type = asm.GetType("DomainsPlugin.Plugin");
// и вызываем функцию из неё через рефлексию
// можно было бы закастить к интерфейсу, если объявить его в
// этой или другой общей dll-ке
var p = Activator.CreateInstance(type);
var method = type.GetMethod(
"GetNames", BindingFlags.Instance | BindingFlags.Public);
var result = (IEnumerable<AssemblyName>)method.Invoke(p, null);
// сохраняем результат. это поле будет доступно из первоначального домена
Result = result.ToList();
}
}
}
In my car from Visual Studio,mscorlib, Version=4. 0. 0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Microsoft.VisualStudio.HostingProcess.Utilities, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3aDomainsMain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullSystem.Core, Version=4. 0. 0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089DomainsPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullUpdating: Resident function (residential)Obtain()() It is possible to return the meaning. But this value must be scattered so that the domen can get down.For our example, we're sending a class. Resident:public class Resident : MarshalByRefObject
{
public List<AssemblyName> Obtain() // <-- поменяли возвращаемый тип
{ // и убрали свойство Result
// загружаем библиотеку
var asm = Assembly.LoadFrom("DomainsPlugin.dll");
var type = asm.GetType("DomainsPlugin.Plugin");
// и вызываем функцию из неё через рефлексию
// можно было бы закастить к интерфейсу, если объявить его в
// этой или другой общей dll-ке
var p = Activator.CreateInstance(type);
var method = type.GetMethod(
"GetNames", BindingFlags.Instance | BindingFlags.Public);
var result = (IEnumerable<AssemblyName>)method.Invoke(p, null);
return result.ToList();
}
}
Now the main code calls look like:// получили данные
var result = resident.Obtain();
// выводим их
foreach (var r in result)
Console.WriteLine(r.ToString());