2010-01-25 3 views
3

J'ai hérité d'un petit langage de script et j'essaye de le porter sur le DLR pour qu'il soit un peu plus facile à gérer. Jusqu'à présent, il a été assez simple. J'ai rencontré un problème en essayant d'appeler dynamiquement des membres d'une variable. Le langage courant fonctionne sur .NET et utilise une boucle d'analyse et de réflexion pour le faire, mais j'espérais m'éloigner de cela. Voici un exemple de langage de script:C# 3.5 DLR Expression.Dynamic Question

string $system1RemoteUri; 
string $dbconnection = $config.GetDBConnection ("somedb"); 
float $minBad = 0.998; 
float $minGood = 0.2; 

$ systen1RemoteURI, minBad $ et Mingood $ sont des variables qui seront définies dans le script, avec DbConnection de $. Cependant, $ dbconnection obtiendra sa valeur à partir d'une variable passée dans $ config. Les 4 variables doivent être disponibles pour l'appelant, donc elles sont passées dans le lambda, initialement comme nul. Voici l'IL Lambda généré (vue de débogage):

.Lambda #Lambda1<Delegate6$1>(
    System.String& $$system1RemoteUri, 
    System.String& $$dbconnection, 
    System.Double& $$minBad, 
    System.Double& $$minGood 
    System.Object $$config) { 
    .Block() { 
     $$minBad = 0.998D; 
     $$minGood = 0.2D 
    } 

    //Some assignment similar to... 
    //.Dynamic Call GetDBConnection($config, "somedb"); 
} 

Ce que je suis en train de comprendre comment utiliser Expression.Dynamic pour émettre le config.GetDBConnection $ (le « somedb »). De regarder des exemples dans les bibliothèques de Sympl je crois que l'IL devrait ressembler à: .Dynamic Appelez GetdbConnection ($ config, "somedb") mais je ne peux pas comprendre comment réellement l'émettre de Expression.Dynamic.

Il semble vouloir un CallSiteBinder que je ne peux pas créer correctement, et je ne comprends pas ce que l'ordre des paramètres est à Expression.Dynamic, car il semble vouloir seulement le "membre" invoqué, et non la base.

Je ne connais pas le type d'exécution $ config c'est juste un objet qui implémente une fonction appelée GetDBConnection (string). Ceci n'est pas fourni par une interface ou une classe de base.

Toute aide serait appréciée.

Répondre

4

Vous pouvez transformer ceci en un InvokeMemberBinder ou transformer "$ config.GetDBConnection" en GetMember, puis faire une invocation sur le résultat de ce passage $ someDb comme argument.

Pour implémenter votre GetMemberBinder et InvokeMemberBinder, vous pouvez utiliser la classe DefaultBinder DLR de couche externe. Dans le dernier code source IronPython/IronRuby, vous pouvez simplement créer une nouvelle instance DefaultBinder à partir de rien. Ensuite, dans votre FallbackGetMember/FallbackInvoke vous pouvez appeler defaultBinder.GetMember (...) et defaultBinder.Call (qui devrait être renommé Invoke). Cela va traiter la plupart des types de .NET pour vous. Tous les objets qui implémentent IDynamicMetaObjectProvider fonctionneront également avec. Pour les autres opérations dynamiques, vous pouvez utiliser les autres méthodes sur le classeur par défaut. Et si vous voulez commencer à personnaliser votre résolution de surcharge et vos règles de liaison, il y a beaucoup de boutons que vous pouvez utiliser.

Malheureusement, le classeur par défaut n'a pas encore d'implémentation de InvokeMemberBinder, donc il est probablement préférable d'utiliser GetMember/Invoke.

+0

Je venais juste de revenir pour répondre à cette question car j'avais compris à peu près la même chose. Ce qui me lançait, c'est que je ne réalisais pas que je devais passer l'expression de base comme premier paramètre à Set/Get/Invoke et le reste des paramètres après. – GrayWizardx

+0

Existe-t-il un exemple de code pouvant être ajouté à la réponse? –