Pergunta

Alguém sabe de uma maneira de interceptar chamadas de método dynamic (particularmente aqueles que estão indo para RuntimeBinderExceptions raise) com um RealProxy? Eu estava esperando para capturar a exceção e implementar 'método perdido' em cima disso, mas parece ser jogado antes do interceptor recebe um olhar-in.

Meu teste apenas se parece com:

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

Onde World não é realmente implementado em DynamicObject. O interceptor é bastante simples - Eu estava esperando para verificar IMethodReturnMessage.Exception para RuntimeBinderException e avançar para algo como:

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

Infelizmente, tudo o que vejo na minha interceptor algumas chamadas para GetType, e não no método World inexistente.

Na falta deste - Alguém sabe se há uma versão DynamicProxy que funciona feliz em .NET 4.0 ainda que poderia ter abordado o problema

?
Foi útil?

Solução

Vou começar com a resposta longa. Cada ligamento de uma operação dinâmica em C # faz aproximadamente estas três coisas nesta ordem:

  1. Pergunte o objeto para vincular-se se implementa IDynamicMetaObjectProvider ou é um objeto COM, e se isso falhar, então ...
  2. Bind a operação para uma operação em um-old-clr-objeto simples usando a reflexão, e se isso falhar, então ...
  3. Voltar a DynamicMetaObject que representa um fracasso total para bind.

Você está vendo as chamadas GetType porque no passo 2, o C aglutinante # runtime está refletindo sobre você para tentar descobrir se você tem um método "World" que é apropriado ao chamado, e isso está acontecendo porque a implementação IDynamicMetaObjectProvider de Olá, se houver, não poderia vir com nada de especial para fazer.

Infelizmente para você, pelo tempo que o RuntimeBinderException é jogado, não estamos mais vinculativo. A exceção sai da fase de execução da operação dinâmica, em resposta ao objeto meta devolvido devido a etapa 3. A única oportunidade para você pegá-lo é no site da chamada actual.

Assim que a estratégia não vai funcionar para você, se você quiser implementar method_missing em C #. Você tem algumas opções embora.

Uma opção fácil é implementar IDynamicMetaObjectProvider em sua MethodMissingInterceptor, e adiar para a implementação IDMOP do objeto embrulhado. Em caso de falha por parte do IDMOP interior, você pode ligar para o que quiser (talvez uma chamada para um delegado method_missing armazenado no interceptor). A desvantagem aqui é que isso só funciona para objetos que são conhecidos por serem objetos dinâmicos, por exemplo, aquelas que implementam IDMOP para começar. Isso é porque você está inserindo-se, basicamente, entre os passos 1 e 2.

Outra alternativa que eu posso pensar é implementar IDynamicMetaObjectProvider, e nele, responder positivamente a todos os ligam, retornando uma chamada para um método que (a) produz o mesmo código o compilador C # teria produzido para ligar em primeiro lugar e (b) pega RuntimeBinderException para chamar um método method_missing. A desvantagem aqui é que seria muito complicado - necessidade você'd para gerar tipos de representante arbitrárias ea IL que usa-los, contra os tipos públicos em tempo de execução pasta C # montagem que, francamente, não significou para o consumo público. Mas pelo menos você deseja obter método faltando contra todas as operações.

Eu tenho certeza que existem outras estratégias que eu não tenha pensado, como você parece estar insinuando sobre o uso de proxies de comunicação remota. Eu não posso imaginar o que eles se parecem com embora e eu não posso dizer se eles estariam bem sucedido.

O cerne do problema aqui é que o C # 4.0 não tem um projeto que antecipa o seu desejo de fazer isso. Especificamente, você não pode facilmente inserir-se entre as etapas 2 e 3. Isso me traz à resposta curta, que é muito, C # 4.0 não tem method_missing.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top