Pregunta

Imagine un método con la siguiente firma:

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

El valor en data debe ser asignado a cualquiera de los dos A, B, C o nada, dependiendo del valor de id.En resumen, si id == "A" entonces A = data;

El problema es que el cuerpo de este método lo escribe un humano pero la firma se genera en tiempo de ejecución.Debido a esto, no es posible codificar la lógica porque en el momento del diseño se desconoce cuántos parámetros de referencia habrá y cómo se llaman.Este fragmento de código se puede insertar en cualquier número de métodos, cada uno potencialmente con una firma diferente, y tiene que funcionar en todos y cada uno de ellos.

Sé cómo obtener todos los parámetros del método en el que se encuentra actualmente, pero no puedo entender cómo asignar un valor a uno de estos parámetros.Lo que estoy buscando es algo como lo siguiente:

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;
    }
  }
}
¿Fue útil?

Solución

No puede acceder a los parámetros por nombre, ya que realmente no puede utilizar la reflexión sobre variables/parámetros.Es posible que tenga algunas opciones si se tratara de IL, pero no realmente en C#.Mi consejo sería:cambie la API, tal vez algo que involucre una matriz o (quizás mejor) un diccionario.Considerar:

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

No estoy seguro si eso ayuda...pero lo que intentas hacer no es realmente compatible con la reflexión.La otra opción es generar este método dinámicamente, ya sea como parte de su proceso de compilación o mediante IL.Cualquiera debería estar bien.Por lo tanto, esencialmente podría generar (como C# o (en tiempo de ejecución) 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 */
    }
}

Un enfoque adicional:el objeto escrito:decir que tienes:

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

dónde obj es un objeto con propiedades como "A", "B", "C";entonces lo que estás intentando generar es:

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

que por supuesto se puede hacer con reflexión:

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

o si el rendimiento es crítico, algo como miembro rápido:

var wrapped = ObjectAccessor.Create(obj); 
wrapped[id] = data;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top