.NET Framework
отражение
Поиск…
Что такое Ассамблея?
Ассембли являются строительным блоком любого приложения Common Language Runtime (CLR) . Каждый тип, который вы определяете вместе со своими методами, свойствами и их байт-кодом, компилируется и упаковывается внутри сборки.
using System.Reflection;
Assembly assembly = this.GetType().Assembly;
Ассембли самодокументируются: они содержат не только типы, методы и их код IL, но также и метаданные, необходимые для их проверки и использования, как при компиляции, так и во время выполнения:
Assembly assembly = Assembly.GetExecutingAssembly();
foreach (var type in assembly.GetTypes())
{
Console.WriteLine(type.FullName);
}
Ассембли имеют имена, которые описывают их полную, уникальную идентичность:
Console.WriteLine(typeof(int).Assembly.FullName);
// Will print: "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Если это имя содержит PublicKeyToken
, оно называется сильным именем . Сильным обозначением сборки является процесс создания подписи с использованием закрытого ключа, который соответствует открытому ключу, распространяемому вместе с сборкой. Эта подпись добавляется в манифест Ассамблеи, который содержит имена и хэши всех файлов, составляющих сборку, и его PublicKeyToken
становится частью имени. Ассембли, имеющие такое же сильное имя, должны быть одинаковыми; сильные имена используются для управления версиями и для предотвращения конфликтов сборки.
Как создать объект T с помощью Reflection
Использование конструктора по умолчанию
T variable = Activator.CreateInstance(typeof(T));
Использование параметризованного конструктора
T variable = Activator.CreateInstance(typeof(T), arg1, arg2);
Создание объекта и настройка свойств с использованием отражения
Допустим, у нас есть класс Classy
который обладает свойством Propertua
public class Classy
{
public string Propertua {get; set;}
}
для установки Propertua
с использованием отражения:
var typeOfClassy = typeof (Classy);
var classy = new Classy();
var prop = typeOfClassy.GetProperty("Propertua");
prop.SetValue(classy, "Value");
Получение атрибута enum с отражением (и кэширование)
Атрибуты могут быть полезны для обозначения метаданных на перечислениях. Получение значения этого может быть медленным, поэтому важно кэшировать результаты.
private static Dictionary<object, object> attributeCache = new Dictionary<object, object>();
public static T GetAttribute<T, V>(this V value)
where T : Attribute
where V : struct
{
object temp;
// Try to get the value from the static cache.
if (attributeCache.TryGetValue(value, out temp))
{
return (T) temp;
}
else
{
// Get the type of the struct passed in.
Type type = value.GetType();
FieldInfo fieldInfo = type.GetField(value.ToString());
// Get the custom attributes of the type desired found on the struct.
T[] attribs = (T[])fieldInfo.GetCustomAttributes(typeof(T), false);
// Return the first if there was a match.
var result = attribs.Length > 0 ? attribs[0] : null;
// Cache the result so future checks won't need reflection.
attributeCache.Add(value, result);
return result;
}
}
Сравните два объекта с отражением
public class Equatable
{
public string field1;
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
var type = obj.GetType();
if (GetType() != type)
return false;
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (var field in fields)
if (field.GetValue(this) != field.GetValue(obj))
return false;
return true;
}
public override int GetHashCode()
{
var accumulator = 0;
var fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (var field in fields)
accumulator = unchecked ((accumulator * 937) ^ field.GetValue(this).GetHashCode());
return accumulator;
}
}
Примечание: в этом примере выполняется сравнение на основе полей (игнорирование статических полей и свойств) для простоты