40

我正在编写一个工具来报告有关在我的客户系统中跨环境和区域部署的 .NET 应用程序的信息。

我想读取这些程序集中的程序集属性值。

这可以使用 来实现Assembly.ReflectionOnlyLoad,但是即使这种方法也会使程序集保持加载。这里的问题是我不能从不同的路径加载两个同名的程序集,所以自然不能比较部署在不同系统中的同一个应用程序。

在这一点上,我假设解决方案将涉及使用临时AppDomains。

有人可以详细说明如何将一个程序集加载到另一个程序集中AppDomain,从中读取属性然后卸载AppDomain吗?

这需要适用于文件系统上的程序集以及 URL 地址上的程序集。

4

5 回答 5

52

System.Reflection.Assembly.ReflectionOnlyLoad (String) 的 MSDN 文档中

仅反射上下文与其他上下文没有什么不同。加载到上下文中的程序集只能通过卸载应用程序域来卸载。

因此,恐怕卸载程序集的唯一方法是卸载应用程序域。要创建一个新的 AppDomain 并将程序集加载到其中:

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

private void LoaderCallback()
{
    Assembly.ReflectionOnlyLoad("YourAssembly");
    // Do your stuff here
}
于 2008-10-22T11:30:39.283 回答
10

虽然不是真正关于卸载程序集,但如果您只是想获取可以使用的文件的版本号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; }
于 2009-04-09T09:19:00.510 回答
9

您可以在新的 AppDomain 中创建一个实例并在该实例中执行您的代码。

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);

这是参考加载器

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;
    }
}
于 2016-06-22T13:48:15.180 回答
4

您可以尝试使用非托管元数据 API,它是 COM,可以通过某种包装器轻松地从 .NET 应用程序中使用。

于 2008-10-22T11:33:20.777 回答
2

您必须使用应用程序域,没有其他方法可以卸载程序集。基本上你必须使用这样的代码:

AppDomain tempDomain = AppDomain.CreateDomain("Temp Domain");
tempDomain.Load(程序集);
AppDomain.Unload(tempDomain);

于 2008-10-22T11:36:24.093 回答