Анонимные типы. Существуют ли какие-либо отличительные характеристики?
Есть ли что-нибудь для использования, чтобы определить, является ли тип на самом деле анонимным типом? Например, интерфейс и т.д.
Цель состоит в том, чтобы создать что-то вроде следующего...
//defined like...
public static T Get<T>(this IAnonymous obj, string prop) {
return (T)obj.GetType().GetProperty(prop).GetValue(obj, null);
}
//...
//And then used like...
var something = new { name = "John", age = 25 };
int age = something.Get<int>("age");
Или это просто красота анонимного типа? Нельзя идентифицировать его сам, потому что он принимает новую форму?
Примечание. Я понимаю, что вы можете написать метод расширения для класса object, но, на мой взгляд, это кажется немного излишним.
Ответы
Ответ 1
EDIT: приведенный ниже список относится к анонимным типам С#. VB.NET имеет разные правила - в частности, он может генерировать изменчивые анонимные типы (и делает по умолчанию). Джаред отметил в комментарии, что стиль именования тоже отличается. В основном это все довольно хрупкое...
Вы не можете идентифицировать его в общем ограничении, но:
- Это будет класс (а не интерфейс, enum, struct и т.д.).
- Он будет использовать CompilerGeneratedAttribute
- Он будет переопределять Equals, GetHashCode и ToString
- Он будет находиться в глобальном пространстве имен
- Он не будет вложен в другой тип
- Он будет внутренним
- Он будет запечатан
- Он будет выводиться непосредственно из
object
- Он будет общим с таким количеством параметров типа, как свойства. (У вас может быть нетривиальный анонимный тип без свойств. Это немного бессмысленно.)
- Каждое свойство будет иметь параметр типа с именем, включающим имя свойства, и будет иметь этот параметр типа, например. свойство Name становится свойством типа < > _ Name
- Каждое свойство будет общедоступным и доступным только для чтения
- Для каждого свойства будет соответствующее частное поле readonly
- Других свойств или полей не будет.
- Будет конструктор, принимающий один параметр, соответствующий каждому параметру типа, в том же порядке, что и параметры типа
- В каждом методе и свойстве будет применен DebuggerHiddenAttribute.
- Название типа начнется с "< > " и будет содержать "Анонимный тип"
Однако очень мало этого гарантируется спецификацией - так что все они могут измениться в следующей версии компилятора, или если вы используете Mono и т.д.
Ответ 2
Насколько я помню, существует [CompilerGenerated]
marker... 2 сек.
Плюс имя будет причудливым, и это будет общий тип; -p
Собственно, для "get" и т.д. я, вероятно, просто использовал бы статический (нерасширяющий) метод.
Если вам просто нужен способ получить значение из экземпляра anon-type (в более поздний момент времени), возможно, наилучшим вариантом является лямбда - обратите внимание, что вам нужно несколько трюков, чтобы снять это:
static void Main()
{
var foo = new { name = "John", age = 25 };
var func = Get(foo, x => x.age);
var bar = new { name = "Marc", age = 30 };
int age = func(bar);
}
// template here is just for type inference...
static Func<TSource, TValue> Get<TSource, TValue>(
TSource template, Func<TSource, TValue> lambda)
{
return lambda;
}
(отредактируйте комментарий). Определенно этот атрибут:
var foo = new { A = "B" };
Type type = foo.GetType();
CompilerGeneratedAttribute attrib = (CompilerGeneratedAttribute) Attribute.GetCustomAttribute(
type, typeof(CompilerGeneratedAttribute)); // non-null, therefore is compiler-generated
Ответ 3
Для целей методов расширения невозможно отличить анонимный тип. Методы расширения работают, указав метод для типа времени компиляции. Анонимные типы не поддаются определению и поэтому не отображаются во время компиляции. Это делает их несовместимыми с методами расширения.