Pregunta

Estoy tratando de construir una biblioteca para simplificar las llamadas de enlace tardío en C #, y tengo problemas para tring con parámetros de referencia. Tengo el siguiente método para agregar un parámetro utilizado en una llamada al 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;
    }

Y eso no funciona con los tipos de valor, porque se encuadran como un objeto, por lo que no se modifican. Por ejemplo:

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);

Eso no funciona. La llamada de enlace tardío es exitosa, y la Lista interna que contiene los parámetros (_parameters) se modifica, pero no el valor fuera de la llamada.

¿Alguien sabe una manera simple de superar esta limitación? La firma AddParameter no se puede modificar, ya que con las llamadas de enlace tardío, no se puede saber de antemano el Tipo de los parámetros (y de cualquier manera se insertan todos los parámetros para una llamada dentro de una matriz de objetos antes de realizar la llamada)

Gracias de antemano.

¿Fue útil?

Solución

Si el valor está cambiando dentro del método , deberá declarar una variable temporal ( object ) para pasar ( ref ) a el método, y luego desempaquéalo tú mismo:

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

Tenga en cuenta que esto no le permitirá actualizar el valor después del evento. Algo parecido a un evento o devolución de llamada podría ser una forma alternativa de pasar los cambios a la persona que llama.

Tenga en cuenta también que C # 4.0 tiene algunos trucos para ayudar con este solo en el contexto de las llamadas COM (donde ref object es tan común [además, por supuesto, dinámico para enlace tardío, como señala Jon]).

Otros consejos

Su método no está cambiando el value de todos modos, ¿por qué lo pasa por referencia? Puede tener sentido, pero no está realmente claro para mí. Tenga en cuenta que el código de muestra que proporcionó no se compilaría de todos modos, ya que los argumentos ref tienen que ser exactamente del mismo tipo que el parámetro.

(Además, ¿sabe que C # 4.0 y .NET 4.0 tendrán compatibilidad integrada para la vinculación tardía? Lo más probable es que la versión integrada en el idioma sea más fácil de usar que una versión solo de biblioteca. ¿Está seguro? ¿Vale la pena pasar tiempo en la biblioteca en este momento?)

EDITAR: el código que ha proporcionado realmente no se compilará. No obtienes boxeo para los parámetros ref , precisamente porque el argumento y los tipos de parámetros tienen que ser exactamente los mismos. Aquí hay un código de muestra para probarlo:

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

    static void Foo(ref object x)
    {
    }
}

Si su código actual está compilando , entonces no es el código que presentó en la pregunta. Quizás tenga otra sobrecarga para AddParameter que acepta ref int ?

Ok, gracias a las correcciones de Jon Skeet y el código de Mark Gravell, se me ocurrió esta interfaz:

        //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];

No es exactamente como lo había imaginado, pero es mucho más simple y legible que mi interfaz 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];

Muchas gracias por su ayuda gente :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top