Question

Imagine a method with the following signature:

public void ExampleMethod(string id, object data, 
                          ref object A, ref object B, ref object C)
{
  //...
}

The value in data needs to be assigned to either A, B, C or nothing, depending on the value of id. In short, if id == "A" then A = data;

The problem is that the body of this method is typed by a human but the signature is generated at runtime. Because of this, it is not possible to hard-code the logic because it is unknown at design-time how many ref parameters there will be and what they are called. This piece of code may be inserted into any number of methods, each potentially with a different signature, and it has to work in each and every one.

I know how to get all the parameters of the method one is currently in, but I can't figure out how to assign a value to one of these parameters. What I'm looking for is something like the following:

public void ExampleMethod(string id, object data, 
                          ref object A, ???????, ref object Z)
{
  MethodBase method = MethodBase.GetCurrentMethod();
  foreach (ParameterInfo parameter in method.GetParameters())
  { 
    if (id == parameter.Name)
    {
      // Problem: assign data to parameter.
      return;
    }
  }
}
Was it helpful?

Solution

You can't access parameters by name, as you can't really use reflection on variables/parameters. You might have some options if this was IL, but not really in C#. My advice would be: change the API, maybe something involving either an array or (perhaps better) a dictionary. Consider:

public void ExampleMethod(string id, object data,
        IDictionary<string,object> args) {
    args[id] = data;
}

Not sure if that helps... but what you are trying to do is not really reflection-friendly. The other option is to generate this method dynamically, either as a part of your build process, or via IL. Either should be fine. So it could essentially generate (as either C# or (at runtime) IL):

public void ExampleMethod(string id, object data, 
                          ref object A, ref object B, ref object C)
{
    switch(id) {
        case "A": A = data; break;
        case "B": B = data; break;
        case "C": C = data; break;
        default: /* do something */
    }
}

An additional approach: the typed object: say you have:

public void ExampleMethod(string id, object data, SomeType obj) {...}

where obj is an object with properties such as "A", "B", "C"; then what you are trying to generate is:

switch(id) {
    case "A": obj.A = data; break;
    case "B": obj.B = data; break;
    case "C": obj.C = data; break;
    default: /* do something */
}

which can of course be done with reflection:

var prop = obj.GetType().GetProperty(id);
prop.SetValue(obj, data, null);

or if performance is critical, something like fast-member:

var wrapped = ObjectAccessor.Create(obj); 
wrapped[id] = data;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top