Pergunta

Estou tring para construir uma biblioteca para simplificando chamadas de ligação tardia em C #, e eu estou começando problemas tring com parameteres referência. Eu tenho o seguinte método para adicionar um parâmetro usado em uma chamada de método

    public IInvoker AddParameter(ref object value)
    {
        //List<object> _parameters = new List<object>();
        _parameters.Add(value);          

        //List<bool> _isRef = new List<bool>();
        _isRef.Add(true);

        return this;
    }

E isso não funciona com tipos de valor, porque eles são encaixotados como um objeto, portanto, eles não são modificados. Por exemplo:

int param1 = 2;
object paramObj = param1;
//MulFiveRef method multiplies the integer passed as a reference parameter by 5:
//void MulFiveRef(ref int value) { value *= 5; }
fi.Method("MulFiveRef").AddParameter(ref paramObj);

Isso não funciona. A chamada ligação tardia for bem sucedida, ea lista interna que detém os parameteres (_parameters) não são modificados, mas não o valor fora da chamada.

Alguém sabe uma maneira simples de superar essa limitação? A assinatura addParameter não podem ser modificados, como acontece com as chamadas ligação tardia, não é possível saber com antecedência o tipo de parâmetros (e de qualquer forma você inserir todos os parâmetros para uma chamada dentro de uma matriz de objeto antes de fazer a chamada)

Agradecemos antecipadamente.

Foi útil?

Solução

Se o valor está mudando dentro do método , você precisará declarar uma variável temporário (object) para passar (ref) para o método, e unbox-lo sozinho depois:

    int i = 3;
    //...
    object obj = i;
    Foo(ref obj);
    i = (int)obj;

Note que isso não irá permitir que você atualizar o valor após o evento. Algo como um evento ou de retorno de chamada pode ser uma forma alternativa de passar alterações de volta para o chamador.

Note-se também que o C # 4.0 tem alguns truques para ajudar com esta única no contexto das chamadas COM (onde ref object é tão comum [mais claro dynamic para a ligação tardia, como observa Jon]).

Outras dicas

Seu método não está mudando value de qualquer maneira - por que você está passando-o por referência? Pode fazer sentido, mas não é muito claro para mim. Note que o código de exemplo que você forneceu não compilar de qualquer maneira, como argumentos ref tem que ser exatamente do mesmo tipo que o parâmetro.

(Além disso, você está ciente de que o C # 4.0 e .NET 4.0 terá suporte embutido para a ligação tardia? As chances são de que a versão integrada de línguas vai ser mais fácil de usar do que uma biblioteca de apenas um. Tem certeza vale a pena passar um tempo na biblioteca neste momento no tempo?)

EDIT: O código que você forneceu realmente não irá compilar. Você não consegue boxe para parâmetros ref, precisamente porque os tipos de argumento e parâmetro tem que ser exatamente o mesmo. Aqui está um código de exemplo para provar isso:

public class Test
{
    static void Main()
    {
        int i;
        Foo(ref i); // Won't compile - error CS1502/1503
    }

    static void Foo(ref object x)
    {
    }
}

Se o seu código atual é compilação, então não é o código apresentado na pergunta. Talvez você tem uma outra sobrecarga para AddParameter que aceita ref int?

Ok, graças a correções Jon Skeet e código Mark Gravell, eu vim acima com esta interface:

        //This will be created with a factory
        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());

        int param1 = 2;
        object paramObj = param1;

        invoker.AddParameter(ref paramObj).Invoke("MulFiveRef");

        param1 = (int)invoker.Parameters[0];

Não é exatamente como eu imaginei, mas é a maneira mais simples e legível que minha interface anterior:

        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());
        int refValue = 10;
        object[] args = Args.Build(refValue);

        invoker.Call("MulFiveRef", Args.ByRefIndexs(0), args);

        refValue = (int)args[0];

Muito obrigado pela vossa ajuda as pessoas:)

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