【问题标题】:Assign value to method parameter为方法参数赋值
【发布时间】:2012-03-18 19:01:42
【问题描述】:

想象一个具有以下签名的方法:

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

data 中的值需要分配给 ABC 或什么都不分配,具体取决于 id 的值。简而言之,如果id == "A" 那么A = data;

问题是这个方法的主体是由人输入的,但签名是在运行时生成的。因此,不可能对逻辑进行硬编码,因为在设计时不知道会有多少 ref 参数以及它们被称为什么。这段代码可以插入到任意数量的方法中,每个方法都可能具有不同的签名,并且它必须在每个方法中都有效。

我知道如何获取当前方法一的所有参数,但我不知道如何为这些参数之一赋值。我正在寻找类似以下内容:

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

【问题讨论】:

  • 会生成函数签名还是修复?
  • 不清楚你的意思 - 为什么你不控制方法体?为什么不能只在方法体中做正确的事?如果您可以在此处提供更多上下文,听起来它真的会有所帮助。 (老实说,这也是一个非常奇怪的设计......)
  • @Henk,签名是在运行时生成的,所以在设计时不知道。我在帖子中添加了一些额外的信息。
  • @Jon,我控制着方法体。我无法控制方法签名。
  • @David 但您肯定可以检测签名,并相应地编写方法吗?场景非常不清楚......

标签: c# .net reflection methodbase parameterinfo


【解决方案1】:

您不能通过名称访问参数,因为您不能真正对变量/参数使用反射。如果这是 IL,您可能会有一些选择,但在 C# 中则不然。我的建议是:更改 API,可能涉及数组或(也许更好)字典。考虑:

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

不确定这是否有帮助...但是您尝试做的并不是真正的反射友好。另一种选择是动态生成此方法,或者作为构建过程的一部分,或者通过 IL。两者都应该没问题。所以它本质上可以生成(作为 C# 或(在运行时)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 */
    }
}

另一种方法:类型化对象:说你有:

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

其中obj 是具有“A”、“B”、“C”等属性的对象;那么您要生成的是:

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

当然可以通过反射来完成:

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

或者如果性能很关键,比如fast-member:

var wrapped = ObjectAccessor.Create(obj); 
wrapped[id] = data;

【讨论】:

  • 感谢 Marc,但现阶段无法更改 API。代码已经存在,我无法承担分发重大更改的费用。我希望可以分配类似于 FieldInfo.SetValue 的参数...我猜不是。
  • @DavidRutten 确实,他们不能
  • @DavidRutten 如果您可以更清楚地了解上下文,我也许可以提供更多帮助;例如,如果这是一个抽象方法或接口方法,并且您需要生成具体的实现,那么可以通过元编程来完成,而不会有太多的痛苦
  • 这段代码最终会出现在可视化编程语言中的 Script 对象中(参见图片:tinyurl.com/7g9l94w)。代码编辑器中的灰线是根据组件的布局生成的。显然,这是一个相当复杂的案例,但我们可以采取其他方法,因为整个 ParameterInfo 事情似乎行不通。
猜你喜欢
  • 2011-04-07
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2012-08-18
  • 2018-04-14
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多