Question

Quelqu'un sait-il d'un moyen d'intercepter les appels de méthode dynamic (en particulier ceux qui vont lever RuntimeBinderExceptions) avec un RealProxy? J'espérais attraper l'exception et mettre en œuvre la « méthode manquante » au-dessus de cela, mais il semble être jeté avant l'intercepteur reçoit un coup d'oeil dans.

Mon test ressemble:

dynamic hello = MethodMissingInterceptor<DynamicObject>.Create();
Assert.AreEqual("World", hello.World());

World est pas réellement mis en œuvre sur DynamicObject. L'intercepteur est assez simple - j'espérais vérifier IMethodReturnMessage.Exception pour RuntimeBinderException et transmettre à quelque chose comme:

public IMessage MethodMissing(IMethodCallMessage call)
{
    return new ReturnMessage(call.MethodBase.Name, new object[0], 0, call.LogicalCallContext, call);
}

Malheureusement, tout ce que je vois dans mon intercepteur sont des appels à GetType, et non pas la méthode de World non existant.

A défaut - personne ne sait s'il y a une version DynamicProxy courir joyeusement sur .NET 4.0 mais qui aurait abordé le problème

Était-ce utile?

La solution

Je vais commencer par la longue réponse. Chaque liaison d'une opération dynamique en C # fait environ ces trois choses dans cet ordre:

  1. Demandez l'objet de se lier si elle met en œuvre IDynamicMetaObjectProvider ou est un objet COM, et si cela échoue, alors ...
  2. Liez l'opération à une opération sur une plaine ancienne clr-objet en utilisant la réflexion, et si cela échoue, alors ...
  3. Retourne une DynamicMetaObject qui représente un échec total pour se lier.

Vous voyez le GetType appels parce à l'étape 2, le liant C # d'exécution reflète sur vous pour essayer de savoir si vous avez une méthode « World » qui convient d'appeler, et cela se produit parce que la mise en œuvre de IDynamicMetaObjectProvider de bonjour, s'il y en a un, ne pouvait pas arriver à quelque chose de spécial à faire.

Malheureusement pour vous, au moment où le RuntimeBinderException est jeté, nous ne sommes plus contraignants. L'exception vient de la phase d'exécution de l'opération dynamique, en réponse à l'objet méta retour en raison de l'étape 3. La seule occasion pour vous de l'attraper est sur le site d'appel réel.

Alors que la stratégie ne va pas travailler pour vous si vous voulez mettre en œuvre method_missing en C #. Vous avez quelques options bien.

Une option facile est de mettre en œuvre IDynamicMetaObjectProvider dans votre MethodMissingInterceptor, et remettre à la mise en œuvre de IDMOP de l'objet enveloppé. En cas d'échec de la part de la IDMOP intérieure, vous pouvez lier à tout ce que vous voulez (peut-être un appel à un délégué method_missing stocké dans l'intercepteur). L'inconvénient est que cela ne fonctionne que pour les objets qui sont connus pour être des objets dynamiques, par exemple ceux qui mettent en œuvre IDMOP pour commencer. Ceci est parce que vous vous insérez essentiellement entre les étapes 1 et 2.

Une autre alternative que je peux penser est de mettre en œuvre IDynamicMetaObjectProvider, et en elle, répondre positivement à chaque bind, retourner un appel à une méthode qui (a) produit le même code que le compilateur C # aurait produit à lier en premier lieu et (b) les prises RuntimeBinderException pour appeler une méthode de method_missing. L'inconvénient est que ce serait assez compliqué - besoin RESULTATS DE PROFESSIONNELS pour générer les types de délégués arbitraires et l'IL qui les utilise, contre les types publics dans le C # assemblage de liant d'exécution qui, franchement, ne sont pas destinés à la consommation publique. Mais au moins vous obtiendriez méthode manquante contre toutes les opérations.

Je suis sûr qu'il ya d'autres stratégies que je ne l'ai pas pensé, comme vous semblez être faisant allusion à l'utilisation des procurations au sujet Remoting. Je ne peux pas imaginer à quoi ils ressemblent bien et je ne peux pas dire si elles seraient succès.

Le nœud du problème est ici que C # 4.0 n'a pas un design qui anticipe votre désir de le faire. Plus précisément, vous ne pouvez pas facilement vous insérer entre les étapes 2 et 3. Cela me amène à la courte réponse, qui est désolé, C # 4.0 n'a pas method_missing.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top