将FieldName作为参数传递

时间:2009-05-27 13:45:17

标签: c# reflection anonymous-function

我不太确定我打算做什么,所以我很难找到谷歌的任何线索。

我有几个方法具有相同的逻辑,唯一不同的是它们在对象上使用的属性。

class Foo
{
   public int A(Bar bar)
   {
      return bar.A * 2;
   }

   public int B(Bar bar)
   {
      return bar.B * 2;
   }

   public int C(Bar bar)
   {
      return bar.C * 2;
   }
}

class Bar
{
   public int A;
   public int B;
   public int C;
}

而不是Foo中的三个单独的方法,我想要一个,看起来更像是

的签名
public int X(Bar bar, ??? x)
{
   return bar.x * 2;
}

这可能吗?

11 个答案:

答案 0 :(得分:14)

我第一次误解了这个问题,不好。

您可以使用Reflection:

执行此操作
public int Method(Bar bar, string propertyName)
{
   var prop = typeof(Bar).GetProperty(propertyName);
   int value = (int)prop.GetValue(bar,null);
   return value * 2;
}

然后,你这样称呼它:

Method(bar,"A");

注意,在您的示例中,Bar中的3个变量是公共实例变量。我假设你刚刚为你的样本做了这个,但如果你的真实课程实际上是这样,那就用Rex M的方法。

答案 1 :(得分:10)

internal class Program {
    private static void Main(string[] args) {
        var bar = new Bar {A = 1, B = 2, C = 3};
        Console.WriteLine(new Foo().X(bar, it => it.A));
        Console.WriteLine(new Foo().X(bar, it => it.B));

        // or introduce a "constant" somewhere
        Func<Bar, int> cFieldSelector = it => it.C;
        Console.WriteLine(new Foo().X(bar, cFieldSelector));
    }
}

internal class Foo {
    // Instead of using a field by name, give it a method to select field you want.
    public int X(Bar bar, Func<Bar, int> fieldSelector) {
        return fieldSelector(bar) * 2;
    }

    public int A(Bar bar) {
        return bar.A * 2;
    }

    public int B(Bar bar) {
        return bar.B * 2;
    }

    public int C(Bar bar) {
        return bar.C * 2;
    }
}

internal class Bar {
    public int A;
    public int B;
    public int C;
}

答案 2 :(得分:3)

我会考虑使用匿名代表来获取您的价值。

public int X(Bar bar, Func<Bar,int> getIt)
{
   return getIt(bar) * 2;
}

然后称之为:

var x = X(mybar, x=>x.A);

答案 3 :(得分:0)

您可以使用反射实现此目的。它会产生一些性能影响

答案 4 :(得分:0)

您可以使用PropertyInfo类通过反射检索所需的属性:https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-6099345.html

答案 5 :(得分:0)

public int X(Bar bar, string target)
{
    object value = bar.GetType().GetField(target, BindingFlags.Public | BindingFlags.Instance).GetValue(bar);
    return (int)value * 2;
}

答案 6 :(得分:0)

尝试使用反射。这是一些简单的代码来实现这种效果。

using System.Reflection;    

public int X(Bar bar, FieldInfo x)
{
    return (int)x.GetValue(bar) * 2;
}

现在,您可以通过首先获取Bar上其中一个字段的FieldInfo来调用X.

Bar b = new Bar();
b.A = 20;
b.B = 30;
b.C = 40;

FieldInfo fieldA = typeof(Bar).GetField("A");
int result = X(b, fieldA);

答案 7 :(得分:0)

使用FieldInfo

BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
FieldInfo field = typeof(Bar).GetField("A", flags);

field.SetValue(..)来设置值。

答案 8 :(得分:0)

您可以使用扩展方法..对于您发布的示例..但我想您的示例只是一些更复杂代码的简化版本。

public static class IntExt
{
    //use Bar.A.Double();
    public int Double(this int value)
    {
        return value * 2;
    }
}

答案 9 :(得分:0)

为什么不使用枚举并将其传递给函数以确定使用哪个?似乎世界各地的反思有点向西走向右边......

class Foo
{
   public enum BarChoice { a,b,c };
   public int x(Bar bar, BarChoice bc)
   {
     switch(bc) 
     {
       case a:
         return bar.A * 2;
       case b:
         return bar.B * 2;
       case c:
         return bar.C * 2;
     }
     return int.MinValue;
   }
}

然后你的电话将是

 Foo f = new foo();
 Bar b = new Bar();
 f.x(b, Foo.BarChoice.a);
 f.x(b, Foo.BarChoice.b);
 f.x(b, Foo.BarChoice.c);

答案 10 :(得分:0)

您可以使用ref关键字:

class Foo
{
    public void A(ref int fieldRef)
    {
        fieldRef *= 2;
    }
}

class Bar
{
    public int A;
    public int B;
    public int C;
}

class Program
{
    static void Main(string[] args)
    {
        var bar = new Bar { A = 1, B = 2, C = 3 };
        var foo = new Foo();
        foo.A(ref bar.A);
        foo.A(ref bar.B);
        foo.A(ref bar.C);

        Console.WriteLine(bar.A); // 2
        Console.WriteLine(bar.B); // 4
        Console.WriteLine(bar.C); // 6
    }
}

我对您的示例进行了一些更改,这是不现实的(如@JonasElfström所说,在这种情况下,您可以简单地传递值)。这表明您可以更改字段的值。