Как загрузить сборку .NET для операций отражения и затем выгрузить ее? - PullRequest
36 голосов
/ 22 октября 2008

Я пишу инструмент для сообщения информации о приложениях .NET, развернутых в средах и регионах в системах моего клиента.

Я бы хотел прочитать значения атрибутов сборки в этих сборках.

Этого можно добиться с помощью Assembly.ReflectionOnlyLoad, однако даже при таком подходе сборка загружается. Проблема в том, что я не могу загрузить две сборки с одинаковыми именами из разных путей, поэтому, естественно, я не могу сравнить одно и то же приложение, развернутое в разных системах.

На данный момент я предполагаю, что решение будет включать временные AppDomain s.

Может кто-нибудь подробно описать, как загрузить сборку в другую AppDomain, прочитать атрибуты из нее и затем выгрузить AppDomain?

Это должно работать для сборок в файловой системе, а также для сборок по URL-адресам.

Ответы [ 5 ]

48 голосов
/ 22 октября 2008

Из документации MSDN System.Reflection.Assembly.ReflectionOnlyLoad (String) :

Контекст только для отражения - нет отличается от других контекстов. Сборки, которые загружены в контекст может быть выгружен только выгрузка домена приложения.

Так что, боюсь, единственный способ выгрузить сборку - это выгрузить домен приложения. Чтобы создать новый домен приложения и загрузить в него сборки:

public void TempLoadAssembly()
{
    AppDomain tempDomain = AppDomain.CreateDomain("TemporaryAppDomain");
    tempDomain.DoCallBack(LoaderCallback);
    AppDomain.Unload(tempDomain);
}

private void LoaderCallback()
{
    Assembly.ReflectionOnlyLoad("YourAssembly");
    // Do your stuff here
}
9 голосов
/ 09 апреля 2009

Хотя на самом деле нет необходимости выгружать сборки, если вы просто пытаетесь получить номер версии файла, вы можете использовать System.Diagnostics.FileVersionInfo.

var info = FileVersionInfo.GetVersionInfo(path);

FileVersionInfo обладает следующими свойствами:

public string Comments { get; }
public string CompanyName { get; }
public int FileBuildPart { get; }
public string FileDescription { get; }
public int FileMajorPart { get; }
public int FileMinorPart { get; }
public string FileName { get; }
public int FilePrivatePart { get; }
public string FileVersion { get; }
public string InternalName { get; }
public bool IsDebug { get; }
public bool IsPatched { get; }
public bool IsPreRelease { get; }
public bool IsPrivateBuild { get; }
public bool IsSpecialBuild { get; }
public string Language { get; }
public string LegalCopyright { get; }
public string LegalTrademarks { get; }
public string OriginalFilename { get; }
public string PrivateBuild { get; }
public int ProductBuildPart { get; }
public int ProductMajorPart { get; }
public int ProductMinorPart { get; }
public string ProductName { get; }
public int ProductPrivatePart { get; }
public string ProductVersion { get; }
public string SpecialBuild { get; }
4 голосов
/ 22 октября 2008

Вы можете попробовать использовать API неуправляемых метаданных , который является COM и может легко использоваться из приложения .NET с какой-то оболочкой.

3 голосов
/ 22 июня 2016

Вы можете создать экземпляр в новом домене приложений и выполнить код в этом экземпляре.

var settings = new AppDomainSetup
{
    ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
};
var childDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), null, settings);

 var handle = Activator.CreateInstance(childDomain,
            typeof(ReferenceLoader).Assembly.FullName,
            typeof(ReferenceLoader).FullName,
            false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, null, CultureInfo.CurrentCulture, new object[0]);


var loader = (ReferenceLoader)handle.Unwrap();

//This operation is executed in the new AppDomain
var paths = loader.LoadReferences(assemblyPath);


AppDomain.Unload(childDomain);

Вот это ReferenceLoader

public class ReferenceLoader : MarshalByRefObject
{
    public string[] LoadReferences(string assemblyPath)
    {
        var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
        var paths = assembly.GetReferencedAssemblies().Select(x => x.FullName).ToArray();
        return paths;
    }
}
3 голосов
/ 22 октября 2008

Вы должны использовать домены приложения, другого способа выгрузки сборки нет. В основном вы должны использовать такой код:


AppDomain tempDomain = AppDomain.CreateDomain("Temp Domain");
tempDomain.Load(assembly);
AppDomain.Unload(tempDomain);

...