Domanda

Sto scrivendo uno strumento per riportare informazioni sulle applicazioni .NET distribuite in ambienti e regioni all'interno dei sistemi del mio client.

Vorrei leggere i valori degli attributi degli assembly in questi assembly.

Questo può essere ottenuto usando Assembly.ReflectionOnlyLoad , tuttavia anche questo approccio mantiene carico l'assembly. Il problema qui è che non riesco a caricare due assembly che hanno lo stesso nome da percorsi diversi, quindi naturalmente non posso confrontare la stessa applicazione distribuita in sistemi diversi.

A questo punto presumo che la soluzione comporterà l'utilizzo di AppDomain .

Qualcuno può dettagliare come caricare un assembly in un altro AppDomain , leggere gli attributi da esso e quindi scaricare AppDomain ?

Questo deve funzionare per gli assembly nel file system e per quelli con indirizzi URL.

È stato utile?

Soluzione

Dalla Documentazione MSDN di System.Reflection.Assembly.ReflectionOnlyLoad (String) :

  

Il contesto di sola riflessione è no   diverso dagli altri contesti.   Assiemi che vengono caricati in   il contesto può essere scaricato solo da   scaricando il dominio dell'applicazione.

Quindi, temo che l'unico modo per scaricare un assembly sia scaricare il dominio dell'applicazione. Per creare un nuovo AppDomain e caricare gli assembly in esso:

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

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

Altri suggerimenti

Anche se non si tratta davvero di scaricare gli assembly, se si sta solo cercando di ottenere il numero di versione di un file, è possibile utilizzare System.Diagnostics.FileVersionInfo .

var info = FileVersionInfo.GetVersionInfo(path);

FileVersionInfo ha le seguenti proprietà:

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

Puoi provare a utilizzare API di metadati non gestiti , che è COM e può essere facilmente utilizzato dall'applicazione .NET con un qualche tipo di wrapper.

Devi usare i domini dell'applicazione, non c'è altro modo per scaricare un assembly. Fondamentalmente devi usare un codice come questo:

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

Puoi creare un'istanza nel nuovo AppDomain ed eseguire il tuo codice in quell'istanza.

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

Ecco il 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;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top