a) Si je comprends bien, tous les niveaux fonctionnent actuellement de la même manière: ils exécutent un délégué qui teste les arguments importants pour la règle, puis exécute une opération ou note l'échec (l'échec est noté en définissant un valeur sur le site d'appel ou faire un appel de queue à la méthode de mise à jour). Par conséquent, chaque règle fonctionne comme:
public object Rule(object x, object y) {
if(x is int && y is int) {
return (int)x + (int)y;
}
CallSiteOps.SetNotMatched(site);
return null;
}
Et un délégué à cette méthode est utilisée dans la L0, L1 et L2 caches. Mais le comportement ici pourrait changer (et a changé plusieurs fois au cours du développement). Par exemple, à un moment donné, le cache L2 était un arbre basé sur le type des arguments.
b) Le cache L0 et les caches L1 sont stockés sur l'objet CallSite. Le cache L0 est un seul délégué qui est toujours la première chose à exécuter. Initialement, ceci est réglé à un délégué qui met juste à jour le site pour la 1ère fois. Des appels supplémentaires tentent d'effectuer la dernière opération que le site d'appel a vu.
Le cache L1 comprend les 10 dernières actions vues par le site d'appel. Si le cache L0 échoue, tous les délégués du cache L1 seront essayés.
Le cache L2 réside sur CallSiteBinder. CallSiteBinder doit être partagé entre plusieurs sites d'appel. Par exemple, il devrait y avoir généralement un et un seul classeur de site d'appel additionnel pour la langue en supposant que tous les ajouts sont les mêmes. Si L0 et L1 toutes les règles disponibles dans le cache L2 seront recherchées. Actuellement, la limite supérieure pour le cache L2 est de 128.
c) Les règles peuvent finalement être produites de deux façons. La solution générale consiste à créer un DynamicMetaObject qui inclut à la fois l'arbre d'expression de l'opération à effectuer ainsi que les restrictions (le test) qui déterminent si c'est applicable. Ceci est quelque chose comme:
public DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg) {
return new DynamicMetaObject(
Expression.Add(Expression.Convert(target, typeof(int)), Expression.Convert(arg, typeof(int))),
BindingRestrictions.GetTypeRestriction(target, typeof(int)).Merge(
BindingRestrictions.GetTypeRestriction(arg, typeof(int))
)
);
}
Cela crée la règle qui ajoute deux entiers. Ce n'est pas vraiment correct parce que si vous obtenez autre chose que des entiers, il boucle infiniment - donc habituellement vous faites un tas de contrôles de type, produisez l'addition pour les choses que vous pouvez gérer, et produisez une erreur si vous ne pouvez pas gérer l'addition.
L'autre façon de créer une règle est de fournir directement le délégué. Ceci est plus avancé et permet certaines optimisations avancées pour éviter de compiler du code tout le temps. Pour ce faire, vous substituez BindDelegate sur CallSiteBinder, inspectez les arguments et fournissez un délégué qui ressemble à la méthode Rule que j'ai tapée ci-dessus.
d) ANSWERED b)
e) Je crois que c'est la même question que b)
f) Si vous mettez les restrictions appropriées à alors oui (que vous êtes obligé de faire pour les classeurs standard). Comme les restrictions échoueront parce que vous n'avez pas deux entrées, le DLR sondera les caches et lorsqu'il ne trouvera pas de règle, il appellera le classeur pour produire une nouvelle règle. Cette nouvelle règle reviendra avec un nouvel ensemble de restrictions, sera installé dans les caches L0, L1 et L2, puis effectuera l'opération pour les chaînes à partir de là.
Je ne sais pas pourquoi votre question sur les dates basées sur les ensembles a été supprimée. Comme j'étais sur le point d'afficher la solution, il est apparu comme supprimé. Quoi qu'il en soit, je l'ai posté sur pastebin si vous êtes toujours intéressé. Ne croyez pas les nay-sayers. Ce n'était pas si dur! http://www.copypastecode.com/61556/ –