- PVSM.RU - https://www.pvsm.ru -
Вот и подходит двухнедельный отдых к концу, а вместе с ним и накопившиеся темы с предыдущей встречи сообщества .Net разработчиков на CLRium. Эта серия постов примерно показывает уровень, с которым мы раскрываем темы на этом мастер-классе, а что будет во второй встрече, можно почитать по ссылке: CLRium #2 [1].
Ссылка на проект в GitHub: DotNetEx [8]
На множественных ресурсах время от времени задается вопрос. Можно ли сделать отгружаемые сборки с текущего домена? Так, чтобы попользовался и «давай, до свидания!»? Везде и всегда ответ, который давался – это «нет». Ведь единственное, что можно выгрузить – это домен. Соответственно, если хочется наладить отгрузку, сборку надо помещать в домен, и налаживать между доменами взаимодействие через сериализуемые типы. А это — очень медленное взаимодействие. А мы скажем так. Можно. С ньюансами. Загружать мы будем также в отдельный домен. Но отменим сериализацию при вызове методов между доменами.
Вопросы, которые мы будем решать:
Итак, как всегда, будем решать проблемы по мере появления:
Возьмем некий общий тип. Для упрощения, возьмем тип из mscorlib: IServiceProvider.
Создадим сборку, которую мы собираемся подружить с возможностью отгрузки:
public class Implementation : IServiceProvider
{
public override string ToString()
{
return "Awesome";
}
public object GetService(Type serviceType)
{
return new object();
}
}
public class AppDomainRunner : MarshalByRefObject, IDisposable
{
private AppDomain appDomain;
private Assembly assembly;
private AppDomainRunner remoteRunner;
private void LoadAssembly(string assemblyPath)
{
assembly = Assembly.LoadFile(assemblyPath);
}
public AppDomainRunner(string assemblyPath)
{
// make appdomain
appDomain = AppDomain.CreateDomain("PseudoIsolated", null,
new AppDomainSetup
{
ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
});
// create object instance
remoteRunner = (AppDomainRunner)appDomain.CreateInstanceAndUnwrap(typeof(AppDomainRunner).Assembly.FullName, typeof(AppDomainRunner).FullName);
remoteRunner.LoadAssembly(assemblyPath);
}
public IntPtr CreateInstance(string typename)
{
return remoteRunner.CreateInstanceImpl(typename);
}
private IntPtr CreateInstanceImpl(string typename)
{
return EntityPtr.ToPointer(assembly.CreateInstance(typename));
}
public void Dispose()
{
assembly = null;
remoteRunner = null;
AppDomain.Unload(appDomain);
}
public class Container : IDisposable
{
private AppDomainRunner appdomain;
private Dictionary<Type, Object> instances = new Dictionary<Type, object>();
public Container(string assemblyName)
{
appdomain = new AppDomainRunner(Path.Combine(System.Environment.CurrentDirectory, assemblyName));
}
public void Register<TInterface>(string fullTypeName)
{
instances.Add(typeof (TInterface), EntityPtr.ToInstance<Object>(appdomain.CreateInstance(fullTypeName)));
}
public TInterface Resolve<TInterface>()
{
return (TInterface)(instances[typeof (TInterface)]);
}
public void Dispose()
{
appdomain.Dispose();
}
}
И последнее – использующий код:
static void Main(string[] args)
{
using (var container = new Container("library.dll"))
{
container.Register<IServiceProvider>("IocLibrary.Implementation");
var serviceProvider = container.Resolve<IServiceProvider>();
Console.WriteLine("calling method without proxy: {0}", serviceProvider);
Console.WriteLine("Current domain assemblies: {0}",
string.Join(", ", AppDomain.CurrentDomain.GetAssemblies().Select(asm => asm.GetName().Name).ToArray()));
}
}
Как говорится, сделать отгружаемые типы нельзя, но если хочется, то можно. Необходимо просто как-то передать между доменами указатель на объект и им можно будет на равных правах пользоваться.
Минус способа только один: мы не имеем права использовать объекты после выгрузки сборки. Это минус по одной простой причине: надо дополнительно контролировать порядок отгрузки и потери ссылки на объекты. Но, в общем случае это не проблема =)
Автор: sidristij
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/net/79073
Ссылки в тексте:
[1] CLRium #2: http://habrahabr.ru/company/luxoft/blog/246665/
[2] Image: http://habrahabr.ru/company/luxoft/blog/219619/
[3] Image: http://habrahabr.ru/company/luxoft/blog/238947/
[4] Image: http://habrahabr.ru/company/luxoft/blog/239005/
[5] Image: http://habrahabr.ru/company/luxoft/blog/244095/
[6] Image: http://habrahabr.ru/company/luxoft/blog/247433/
[7] Image: http://habrahabr.ru/company/luxoft/blog/247447/
[8] Image: https://github.com/mumusan/dotnetex
[9] Источник: http://habrahabr.ru/post/247491/
Нажмите здесь для печати.