Útmutató: Szerelvény tartalmának vizsgálata a MetadataLoadContext használatával

A .NET-ben a reflection API alapértelmezés szerint lehetővé teszi a fejlesztők számára a fő végrehajtási környezetbe betöltött szerelvények tartalmának vizsgálatát. Néha azonban nem lehet betölteni egy szerelvényt a végrehajtási környezetbe, például azért, mert egy másik platformra vagy processzorarchitektúrára állították össze, vagy egy referencia-szerelvény. Az System.Reflection.MetadataLoadContext API lehetővé teszi az ilyen szerelvények betöltését és vizsgálatát. A MetadataLoadContext-be betöltött szerelvények csak metaadatként kerülnek kezelésre, azaz megvizsgálhatja a szerelvény típusait, de nem hajthat végre benne semmilyen kódot. A fő végrehajtási környezettől eltérően a MetadataLoadContext rendszer nem tölti be automatikusan a függőségeket az aktuális könyvtárból, hanem az átadott könyvtár által MetadataAssemblyResolver biztosított egyéni kötési logikát használja.

Előfeltételek

A használatához MetadataLoadContexttelepítse a System.Reflection.MetadataLoadContext NuGet csomagot. Bármely .NET Standard 2.0-s szabványnak megfelelő cél-keretrendszerben támogatott, például .NET Core 2.0 vagy .NET Framework 4.6.1.

MetadataAssemblyResolver létrehozása MetadataLoadContexthez

MetadataLoadContext létrehozásához meg kell adni a MetadataAssemblyResolver példányát. A legegyszerűbb módja ennek az PathAssemblyResolver használata, amely a megadott szerelvényútvonal-sztringek gyűjteményéből oldja fel a szerelvényeket. Ennek a gyűjteménynek a közvetlenül vizsgálandó szerelvények mellett az összes szükséges függőséget is tartalmaznia kell. Például, ha egy külső assembly-ben található egyéni attribútumot szeretne elolvasni, vegye fel az assembly-t, különben kivételt okoz. A legtöbb esetben legalább az alapvető szerelvényt, vagyis a beépített rendszertípusokat tartalmazó szerelvényt kell tartalmaznia, például System.Object. Az alábbi kód bemutatja, hogyan hozhatja létre a PathAssemblyResolver a vizsgált szerelvényből és az aktuális futtatókörnyezet alapvető szerelvényéből álló gyűjtemény használatával.

var resolver = new PathAssemblyResolver(new string[] { "ExampleAssembly.dll", typeof(object).Assembly.Location });

Ha az összes BCL-típushoz hozzá kell férnie, az összes futtatókörnyezet-szerelvényt belefoglalhatja a gyűjteménybe. Az alábbi kód bemutatja, hogyan hozhatja létre a PathAssemblyResolver a vizsgált szerelvényből és az aktuális futtatókörnyezet összes szerelvényéből álló gyűjtemény használatával.

// Get the array of runtime assemblies.
string[] runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");

// Create the list of assembly paths consisting of runtime assemblies and the inspected assembly.
var paths = new List<string>(runtimeAssemblies);
paths.Add("ExampleAssembly.dll");

// Create PathAssemblyResolver that can resolve assemblies using the created list.
var resolver = new PathAssemblyResolver(paths);

MetadataLoadContext létrehozása

A létrehozáshoz hívja meg a MetadataLoadContextkonstruktort MetadataLoadContext(MetadataAssemblyResolver, String), és adja át a korábban létrehozott MetadataAssemblyResolver paramétert első paraméterként, az alapvető szerelvény nevét pedig második paraméterként. Kihagyhatja az alapvető szerelvénynevet, amely esetben a konstruktor az alapértelmezett neveket próbálja használni: "mscorlib", "System.Runtime" vagy "netstandard".

A környezet létrehozása után az összeállításokat olyan módszerekkel töltheti be, mint a LoadFromAssemblyPath. Az összes tükrözési API-t használhatja a betöltött szerelvényeken, kivéve azokat, amelyek kódvégrehajtást igényelnek. A GetCustomAttributes metódus magában foglalja a konstruktorok végrehajtását, ezért használja inkább a GetCustomAttributesData metódust, amikor egyéni attribútumokat kell megvizsgálnia a MetadataLoadContext.

A következő kódminta létrehozza MetadataLoadContext, betölti a szerelvényt, és szerelvényattribútumokat ad ki a konzolon:

var mlc = new MetadataLoadContext(resolver);

using (mlc)
{
    // Load assembly into MetadataLoadContext.
    Assembly assembly = mlc.LoadFromAssemblyPath("ExampleAssembly.dll");
    AssemblyName name = assembly.GetName();

    // Print assembly attribute information.
    Console.WriteLine($"{name.Name} has following attributes: ");

    foreach (CustomAttributeData attr in assembly.GetCustomAttributesData())
    {
        try
        {
            Console.WriteLine(attr.AttributeType);
        }
        catch (FileNotFoundException ex)
        {
            // We are missing the required dependency assembly.
            Console.WriteLine($"Error while getting attribute type: {ex.Message}");
        }
    }
}

Ha az egyenlőség vagy a hozzárendelhetőség szempontjából tesztelnie kell a MetadataLoadContext típusokat, csak az ebbe a környezetbe betöltött típusobjektumokat használja. A MetadataLoadContext típusok és a futatásidejű típusok keverése nem támogatott. Vegyünk például egy testedType típust a MetadataLoadContext-ben. Ha meg kell vizsgálnia, hogy egy másik típus rendelhető-e hozzá, ne használjon olyan kódot, mint a typeof(MyType).IsAssignableFrom(testedType). Használja a következőhöz hasonló kódot:

Assembly matchAssembly = mlc.LoadFromAssemblyPath(typeof(MyType).Assembly.Location);
Type matchType = assembly.GetType(typeof(MyType).FullName!)!;

if (matchType.IsAssignableFrom(testedType))
{
    Console.WriteLine($"{nameof(matchType)} is assignable from {nameof(testedType)}");
}

Example

A teljes példakódért tekintse meg a szerelvény tartalmának vizsgálata MetadataLoadContext minta használatával című témakört.

Lásd még