2011-10-04 4 views
5

Possible en double:
Is it possible to declare an anonymous type in C# with a variable/dynamic set of fields?Comment ajouter dynamiquement des propriétés à un objet anonyme?

J'ai construit un générateur de requêtes qui construit une requête en examinant certaines valeurs GET que l'utilisateur a défini dans mon application ASP.NET MVC3. Ce générateur de requête peut ajouter un tri, une limitation et un filtrage (la clause WHERE), puis renvoie la requête construite.

Cette requête va alors à mon dépôt Dapper qui tente d'exécuter la requête avec:

using (IDbConnection connection = new MySqlConnection(ConnectionStringFactory.GetConnectionString(Database.Push))) 
{ 
    connection.Open(); 

    return connection.Query<Notification>(query.QueryString, 
              new 
              { 
               someAnonymousStuffHere = SomeValue 
              }); 
} 

Cependant, les paramètres de la requête (c'est une déclaration préparée) doivent être mis dans un type anonyme. Le problème est: je ne sais pas comment construire dynamiquement ce type anonyme. Ce que je fais maintenant est de pousser tous les paramètres dans un dictionnaire dans le générateur de requête, où la clé est le nom de la propriété et la valeur est, bien, la valeur.

Je ne peux pas simplement définir un type anonyme dans mon générateur de requête, car le générateur se compose de plusieurs étapes, dont certaines ne sont pas exécutées. Donc parfois nous avons 5 paramètres, parfois nous avons 3 paramètres, etc.

J'espère avoir expliqué mon problème assez clairement. N'hésitez pas à demander plus d'informations :) Merci d'avance!

+0

Que comptez-vous faire avec ce type anonyme dont vous ne connaissez pas les membres au moment de la compilation? – Gabe

+0

Le type anonyme va dans la méthode Query, qui mappera probablement les paramètres à l'espace réservé correct dans la requête. –

+0

http://stackoverflow.com/questions/7437043/is-it-possible-to-declare-an-anonymous-type-in-c-with-a-variable-dynamic-set-of devrait avoir votre réponse –

Répondre

2

Les types anonymes sont toujours statiquement typés au moment de la compilation. Je suggère de regarder dans les fonctionnalités de langue dynamic, ou coller avec votre dictionnaire.

Voici un exemple de chargement d'un objet dynamique à partir d'un dictionnaire de clés/valeurs, puis d'y accéder comme s'il s'agissait d'un objet typé statiquement.

//linqpad 
void Main() 
{ 
    IDictionary<string,object> items = new Dictionary<string,object>(); 
    items.Add("test","123"); 

    dynamic props = DynamicProperties.LoadFromDictionary(items); 

    string item = props.test; 

    item.Dump(); 
} 


public class DynamicProperties : DynamicObject 
{ 
    private DynamicProperties(){} 

    private Dictionary<string, object> dictionary = new Dictionary<string, object>(); 

    public static DynamicProperties LoadFromDictionary(IDictionary<string,object> Dictionary) 
    { 
     dynamic dprop = new DynamicProperties(); 
     foreach(var item in Dictionary) 
     { 
      dprop.dictionary.Add(item.Key.ToLower(),item.Value); 
     } 
     return dprop; 
    } 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     string name = binder.Name.ToLower(); 
     Console.WriteLine("Trying to get " + name); 
     return this.dictionary.TryGetValue(name,out result); 
    } 
    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     Console.WriteLine("TrySetMember: " + value.ToString()); 
     this.dictionary[binder.Name.ToLower()] = value; 
     return true; 
    } 
} 
10

Les types anonymes sont simplement une commodité où le compilateur peut créer un type pour vous "à la volée" pour vous éviter de taper. Cependant, il est encore statiquement typé. Si vous avez besoin d'un type "plus intelligent" avec plus de fonctionnalités que vous obtenez d'un type anonyme ou si vous devez passer des instances du type, vous devez créer un type "réel" comme vous le feriez avant que les types anonymes existent.

Une autre option consiste à utiliser la fonctionnalité dynamic. Vous pouvez créer un type dynamique en utilisant par exemple ExpandoObject. Voici un petit exemple sur la façon dont vous pouvez l'utiliser:

dynamic expando = new ExpandoObject(); 
expando.Name = "Martin"; 
if (((IDictionary<String, Object>) expando).ContainsKey("Name")) 
    Console.WriteLine(expando.Name); 

Le expando est vraiment un dictionnaire glorifié et en utilisant un dictionnaire au lieu (comme vous) pourrait se révéler être une meilleure option.

Questions connexes