Обнаружение атрибута в сборке без предварительной загрузки в домен .NET
Интересует возможно ли узнать наличие определенного атрибута во внешней библиотеке без загрузки библиотеки в домен. Есть к примеру две сборки:
// Основная сборка
namespace FirstAsm
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public sealed class InitLoaderAttribute : Attribute
{
public Type InitType { get; }
public InitLoaderAttribute(Type initType)
{
InitType = initType;
}
}
...
}
// Внешняя сборка
[assembly: InitLoader(typeof(MyClass))]
namespace SecondAsm
{
...
}
Стандартного API для таких целей я не нашел. AppDomain.Load не подойдет, т.к. мне прежде всего нужно узнать наличие нужного атрибута. Может есть какие советы
Ответы (1 шт):
Автор решения: MSDN.WhiteKnight
→ Ссылка
В комментариях правильно указали на несколько способов, которые позволяют сделать это:
- Assembly.ReflectionOnlyLoad (.NET Framework)
- System.Reflection.Metadata (.NET Standard 1.1+)
- System.Reflection.MetadataLoadContext (.NET Standard 2.0+)
В .NET Core проще всего воспользоваться третьим способом. Подключаем пакет System.Reflection.MetadataLoadContext. Вот так мы можем прочитать значение атрибута сборки:
using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
namespace MetadataLoadContextSample
{
class Program
{
static int Main(string[] args)
{
string inputFile = @"C:\Test\Example.dll"; //проверяемая сборка
string attrFile = @"C:\Test\InitLoader.dll"; //сборка с определением атрибута
string[] runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");
var paths = new List<string>(runtimeAssemblies);
paths.Add(inputFile);
paths.Add(attrFile);
var resolver = new PathAssemblyResolver(paths);
var context = new MetadataLoadContext(resolver);
using (context)
{
Assembly assembly = context.LoadFromAssemblyPath(inputFile);
foreach (CustomAttributeData attr in assembly.GetCustomAttributesData())
{
if (String.Equals(attr.AttributeType.Name, "InitLoaderAttribute", StringComparison.InvariantCulture))
{
Console.WriteLine(attr.ConstructorArguments[0].Value);
}
}
}
Console.ReadLine();
return 0;
}
}
}