été - Comment charger un assembly.NET pour des opérations de réflexion et le décharger par la suite?




un assembly avec un nom fort est requis (4)

Bien qu'il ne s'agisse pas vraiment de décharger des assemblys, si vous essayez juste d'obtenir le numéro de version d'un fichier, vous pouvez utiliser System.Diagnostics.FileVersionInfo .

var info = FileVersionInfo.GetVersionInfo(path);

FileVersionInfo a les propriétés suivantes:

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

J'écris un outil pour signaler des informations sur les applications .NET déployées dans les environnements et les régions au sein des systèmes de mon client.

J'aimerais lire les valeurs des attributs d'assemblage dans ces assemblages.

Cela peut être réalisé en utilisant Assembly.ReflectionOnlyLoad , mais même cette approche maintient l'ensemble chargé. Le problème ici est que je ne peux pas charger deux assemblées qui ont le même nom à partir de chemins différents, donc naturellement je ne peux pas comparer la même application déployée dans différents systèmes.

À ce stade, je suppose que la solution impliquera l'utilisation de AppDomain temporaire.

Quelqu'un peut-il détailler comment charger un assembly dans un autre AppDomain , en lire les attributs, puis décharger AppDomain ?

Cela doit fonctionner pour les assemblys sur le système de fichiers ainsi que ceux aux adresses URL.


De la documentation MSDN de System.Reflection.Assembly.ReflectionOnlyLoad (String) :

Le contexte de réflexion seule n'est pas différent des autres contextes. Les assemblys qui sont chargés dans le contexte peuvent être déchargés uniquement en déchargeant le domaine d'application.

Donc, je crains que le seul moyen de décharger un assembly est de décharger le domaine d'application. Pour créer un nouvel AppDomain et charger des assemblys dans celui-ci:

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

private void LoaderCallback()
{
    Assembly.ReflectionOnlyLoad("YourAssembly");
    // Do your stuff here
}

Vous pouvez créer une instance dans le nouvel AppDomain et exécuter votre code dans cette instance.

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

Voici le 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;
    }
}

Vous pouvez essayer d'utiliser l' API de métadonnées non gérées , qui est COM et peut facilement être utilisée à partir de l'application .NET avec un type de wrapper.





assembly-attributes