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