Tipi anonimi - Ci sono delle caratteristiche distintive?
-
10-07-2019 - |
Domanda
C'è qualcosa da usare per determinare se un tipo è effettivamente un tipo anonimo? Ad esempio un'interfaccia, ecc.
L'obiettivo è creare qualcosa di simile al seguente ...
//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");
O è solo la bellezza di un tipo anonimo? Niente per identificarlo da solo perché prende una nuova forma?
Nota - Mi rendo conto che puoi scrivere un metodo di estensione per la classe oggetto , ma secondo me sembra un po 'eccessivo.
Soluzione
EDIT: l'elenco seguente si applica ai tipi anonimi C #. VB.NET ha regole diverse - in particolare, può generare tipi anonimi mutabili (e lo fa di default). Jared ha sottolineato nel commento che anche lo stile di denominazione è diverso. Fondamentalmente questo è abbastanza fragile ...
Non puoi identificarlo in un vincolo generico, ma:
- Sarà una classe (piuttosto che interfaccia, enum, struct ecc)
- Avrà CompilerGeneratedAttribute applicato ad esso
- Sostituirà Equals, GetHashCode e ToString
- Sarà nello spazio dei nomi globale
- Non verrà nidificato in un altro tipo
- Sarà interno
- Sarà sigillato
- Deriverà direttamente da
object
- Sarà generico con tanti parametri di tipo quante sono le proprietà. ( puoi avere un tipo anonimo non generico, senza proprietà. Tuttavia è un po 'inutile.)
- Ogni proprietà avrà un parametro di tipo con un nome incluso il nome della proprietà e sarà di quel parametro di tipo, ad es. la proprietà Name diventa una proprietà di tipo < > _Name
- Ogni proprietà sarà pubblica e di sola lettura
- Per ogni proprietà ci sarà un campo privato di sola lettura corrispondente
- Non ci saranno altre proprietà o campi
- Ci sarà un costruttore che accetta un parametro corrispondente a ciascun parametro di tipo, nello stesso ordine dei parametri di tipo
- Ogni metodo e proprietà avrà il DebuggerHiddenAttribute applicato ad esso.
- Il nome del tipo inizierà con " < > " e contiene " AnonymousType "
Tuttavia, molto poco è garantito dalle specifiche, quindi potrebbe cambiare tutto nella prossima versione del compilatore, o se usi Mono ecc.
Altri suggerimenti
Come ricordo, esiste un
Inoltre il nome sarà strano e sarà di tipo generico ;-p
In realtà, per un " get " ecc. Probabilmente userei solo un metodo statico (non di estensione).
Se vuoi solo un modo per ottenere il valore da un'istanza di un tipo anone (in un momento successivo), una lambda è probabilmente l'opzione migliore - nota che hai bisogno di alcuni trucchi per farlo:
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;
}
(modifica il commento) Sicuramente è questo attributo:
var foo = new { A = "B" };
Type type = foo.GetType();
CompilerGeneratedAttribute attrib = (CompilerGeneratedAttribute) Attribute.GetCustomAttribute(
type, typeof(CompilerGeneratedAttribute)); // non-null, therefore is compiler-generated
Ai fini dei metodi di estensione non è possibile distinguere un tipo anonimo. I metodi di estensione funzionano specificando un metodo per un tipo identificabile in fase di compilazione. I tipi anonimi non sono nominabili e pertanto non sono visibili al momento della compilazione. Ciò li rende incompatibili con i metodi di estensione.