Моя цель: Я пишу vsix (расширение Visual Studio), где я хочу скомпилировать проект, а затем загрузить полученный DLL и проверить его через отражение. Из-за того, как написан код, я не могу использовать ReflectionOnlyLoad()
. Если я просто делаю Assembly.Load
, тогда файл заблокирован, пока пользователь не перезапустит всю среду IDE.Assembly.LoadFrom() или Assembly.Load(), способный удалить файл
Я пытаюсь настроить отдельный AppDomain на основе образцов, которые я нашел в Интернете.
Суть его является: 1. Я создал класс Proxy, который МАРШАЛ данные по AppDomain
случаях:
internal class AppDomainProxy : MarshalByRefObject
{
public Assembly GetAssembly(string assemblyPath)
{
return Assembly.LoadFile(assemblyPath);
}
}
Я затем создать экземпляр этого:
var domaininfo = new AppDomainSetup { ApplicationBase = System.Environment.CurrentDirectory, ShadowCopyDirectories = "true", ShadowCopyFiles = "true", LoaderOptimization = LoaderOptimization.MultiDomainHost };
var adevidence = System.AppDomain.CurrentDomain.Evidence;
var domain = System.AppDomain.CreateDomain("reflection", adevidence, domaininfo);
var proxyType = new AppDomainProxy().GetType();
var proxyInstance = (AppDomainProxy)domain.CreateInstanceFromAndUnwrap(proxyType.Assembly.Location, proxyType.FullName);
var loadedAssembly = (proxyInstance as AppDomainProxy).GetAssembly(this._assemblyLocation);
Это не удалось передать мой прозрачный прокси для моего AppDomainProxy
. Чтобы обойти это, можно легко поставить сборочный распознаватель следующим образом:
this.domain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
private Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
{
var loadedAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in loadedAssemblies)
{
if (assembly.FullName == args.Name)
{
return assembly;
}
}
return null;
}
Это прекрасно работает, мой прокси отливают. Однако, когда я вызываю свой метод, вызывается CurrentDomainOnAssemblyResolve
, предлагая мне, что свойство Assembly
не является сериализуемым и поэтому .net просто пытается загрузить сборку с исходной стороны, что приводит к той же проблеме, что и Assembly.Load
. Это легко увидеть, потому что простые образцы Microsoft, такие как , работают нормально.
ОБНОВЛЕНИЕ В качестве обходного пути я просто переместил свой код, который требовал, чтобы сборка выполнялась с другой стороны (внутри домена), а затем возвращала строку назад, которая отлично маршала. Однако я буду держать вопрос открытым, потому что я хочу знать, есть ли решение для актуальной проблемы.
Ну, вы снова вернулись на квадрат, потому что сборка теперь загружена в _both_ AppDomains, и вы можете только «Unload()» один из них. Почему бы не сделать все, что нужно сделать во вторичном AppDomain? – MickyD
@MickyD Согласно обновлению вопроса, это то, что я закончил делать. Но мне это не нравится:/ – zaitsman
Не нравится? В этом весь смысл AppDomains. Создание Appdomain для изоляции для загрузки говорит, что сборка или плагин только для возврата в родительский домен поражает цель песочниц точно так же, если вы создали дочерний поток для выполнения длительной задачи, но только для того, чтобы заблокировать его до завершения , Есть несколько хороших статей, которые я предлагаю вам прочитать в доменах MSDN Magazine re app – MickyD