How to change the type of a nested value inside a method

I am trying to create a library to simplify late binding calls in C # and I am getting alarmed with reference parameters. I have the following way to add a parameter used in a method call

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

      

And this doesn't work with value types because they are placed as objects, so they don't change. For example:

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

      

This does not work. The rest of the bind call succeeds, and the internal list containing the parameters (_parameters) gets changed, but not the value outside of the call.

Does anyone know an easy way to overcome this limitation? The AddParameter signature cannot be changed, as with late binding calls, you cannot know the type of the parameters in advance (and in any case, you are inserting all the parameters to be called inside the object array before making the call)

Thanks in advance.

0


source to share


3 answers


If the value changes inside the method, you need to declare a temp ( object

) variable to pass ( ref

) to the method and then remove it yourself:

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

      



Note that this will prevent you from updating the value after the event. Something like an event or callback could be an alternative way of passing the changes back to the caller.

Note that C # 4.0 has some tricks to help with this only in the context of COM calls (where it is ref object

so common [plus, of course, dynamic

for late binding, as John notes]).

+1


source


Your method doesn't change value

anyway - why are you passing it by reference? It might make sense, but I don't really understand it. Note that the example code you provided will not compile anyway, as the arguments ref

must be exactly the same type as the parameter.

(Also, did you know that C # 4.0 and .NET 4.0 will have built-in support for late binding? Chances are that the language integrated version will be easier to use than the library.Is the library worth the time at this point ?)

EDIT: The code you provided really won't compile. You don't get boxing for the parameters ref

, precisely because the argument and parameter types must be exactly the same. Here's a sample code to verify it:



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

    static void Foo(ref object x)
    {
    }
}

      

If your current code is compiling, then it is not the code you provided in the question. Perhaps you have another overload for AddParameter

that takes ref int

?

+1


source


Ok, thanks to John Skeet's fixes and Mark Gravell's code, I came up with this 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];

      

Not exactly as I imagined, but my previous interface is more simple and easy to read:

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

      

Thanks a lot for helping people :)

0


source







All Articles