如何为反射操作加载.NET程序集并随后卸载它?

时间:2008-10-22 11:24:46

标签: .net assemblies appdomain assembly-attributes

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

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

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

此时我假设解决方案将涉及使用临时AppDomain

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

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

5 个答案:

答案 0 :(得分:48)

来自MSDN documentation of System.Reflection.Assembly.ReflectionOnlyLoad (String)

  

仅反射的背景是否定的   与其他情境不同。   加载到的程序集   上下文只能通过   卸载应用程序域。

因此,我担心卸载程序集的唯一方法是卸载应用程序域。 要创建新的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
}

答案 1 :(得分:9)

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

答案 2 :(得分:4)

您可以尝试使用Unmanaged Metadata API,它是COM,可以通过某种包装器轻松地从.NET应用程序中使用。

答案 3 :(得分:3)

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


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

答案 4 :(得分:3)

您可以在新的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);

这是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;
    }
}