Pergunta

Dada:

interface I
{
}

class B: I
{
}

class C: I
{
}

class A
{

    public void Method(B arg)
    {
    }

    public void Method(C arg)
    {
    }

    public void Method(I arg)
    {
       // THIS is the method I want to simplify.
       if (I is B)
       {
          this.Method(arg as B);
       }
       else if (I is C)
       {
          this.Method(arg as C);
       }
    }
}

Eu sei que há melhores maneiras de conceber este tipo de interações, mas por causa de detalhes o que levaria muito tempo para explicar isso não é possível. Uma vez que este padrão será duplicada muitas vezes, eu gostaria de substituir o lógica condicional com uma implementação genérico que eu poderia usar apenas uma linha. Eu não posso ver uma maneira simples de implementar este método genérico / classe, mas meus instintos me dizem que deveria ser possível.

Qualquer ajuda seria apreciada.

Foi útil?

Solução

O que você quer é dupla expedição, e padrão do visitante em particular.

Outras dicas

Eu colocaria o método dentro da interface e, em seguida, deixar o polimorfismo decidir qual método para chamar

interface I
{
   void Method();
}

class B : I
{
   public void Method() { /* previously A.Method(B) */}
}

class C : I
{
   public void Method() { /* previously A.Method(C) */ }
}

class A
{
   public void Method(I obj)
   { 
     obj.Method();
   }
}

Agora, quando você precisa adicionar uma nova classe, você só precisa implementar I.Method. Você não precisa tocar A.Method.

Esta é meio feio, mas ele começa o trabalho feito:

public void Method(B arg)
{
  if (arg == null) return;
...
}
public void Method(C arg)
{
  if (arg == null) return;
...
}

public void Method(I arg)
{
  this.Method(arg as B);
  this.Method(arg as C);
}

Eu não acho que eu iria fazê-lo desta forma, embora. Realmente dói olhar para isso. Me desculpe, eu te forçou todos a olhar para isso também.

interface I
{ 
} 

class B : I
{
}

class C : I
{
}    

class A 
{
    public void Method(B arg)
    {
        Console.WriteLine("I'm in B");
    }

    public void Method(C arg)
    {
        Console.WriteLine("I'm in C");
    }

    public void Method(I arg)
    {
        Type type = arg.GetType();

        MethodInfo method = typeof(A).GetMethod("Method", new Type[] { type });
        method.Invoke(this, new I[] { arg });
    }
}

Ele não existe em uma conveniente forma withing C # - ver aqui para uma idéia com base na correspondência 's F # padrão, que faz exatamente o que você quer. Você pode fazer algumas coisas com reflexão para selecionar a sobrecarga em tempo de execução, mas que será muito lento, e tem problemas graves se satisfaz qualquer coisa ambas as sobrecargas. Se você tivesse um valor de retorno, você poderia usar o operador condicional;

return (I is B) ? Method((B)I) : ((I is C) ? Method((C)I) : 0);

Mais uma vez -. Não é bonito

Easy. Em Visual Basic eu faço isso o tempo todo usando CallByName.

Sub MethodBase(value as Object)
    CallByName(Me, "RealMethod", CallType.Method, value)

Isso vai chamar a sobrecarga de RealMethod que mais se aproxima do tipo de tempo de execução de valor.

Eu tenho certeza que você pode usar CallByName de C #, importando Microsoft.VisualBasic.Interaction ou criando sua própria versão usando a reflexão.

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