Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass FieldName as a Parameter

I'm not quite sure what I'm attempting to do is called, so I'm struggling to find any clues from google.

I have a couple of methods with the same logic in them, the only thing that differs is the property they are using on an object.

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

Instead of the three separate methods in Foo I want one, with a signature that looks more like

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

Is this possible?

like image 550
Kirschstein Avatar asked May 27 '09 13:05

Kirschstein


3 Answers

I misread the question the first time, my bad.

You can do this with Reflection:

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

Then, you call it like this:

Method(bar,"A");

Just noticed that in your example, the 3 variables in Bar are public instance variables. I'm assuming that you just did this for your sample, but if this is in fact the case in your real class, use Rex M's approach.

like image 86
BFree Avatar answered Nov 04 '22 06:11

BFree


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;
}
like image 11
THX-1138 Avatar answered Nov 04 '22 06:11

THX-1138


I would consider using an anonymous delegate to get your value instead.

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

Then call it like:

var x = X(mybar, x=>x.A);
like image 3
Mark Avatar answered Nov 04 '22 07:11

Mark