Передать FieldName в качестве параметра - PullRequest
4 голосов
/ 27 мая 2009

Я не совсем уверен, что то, что я пытаюсь сделать, называется, поэтому я изо всех сил пытаюсь найти какие-либо подсказки от Google.

У меня есть пара методов с одинаковой логикой, единственное, что отличается, это свойство, которое они используют для объекта.

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

Возможно ли это?

Ответы [ 10 ]

14 голосов
/ 27 мая 2009

Я неправильно понял вопрос в первый раз, мой плохой.

Вы можете сделать это с помощью 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");

Только что заметил, что в вашем примере 3 переменные в Bar являются открытыми переменными экземпляра. Я предполагаю, что вы только что сделали это для своего образца, но если это действительно так в вашем реальном классе, используйте подход Rex M.

11 голосов
/ 27 мая 2009
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;
}
3 голосов
/ 27 мая 2009

Я хотел бы рассмотреть возможность использования анонимного делегата для получения вашего значения.

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

Тогда назовите это как:

var x = X(mybar, x=>x.A);
0 голосов
/ 27 мая 2009

Почему бы не использовать перечисление и не передать его в функцию, чтобы определить, что использовать? Кажется, отражение - это своего рода движение на запад по всему миру, чтобы сделать шаг вправо ...

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);
0 голосов
/ 27 мая 2009

вы можете использовать метод расширения ... для примера, который вы разместили ... но я думаю, что ваш пример - просто упрощенная версия более сложного кода.

public static class IntExt
{
    //use Bar.A.Double();
    public int Double(this int value)
    {
        return value * 2;
    }
}
0 голосов
/ 27 мая 2009

Использовать FieldInfo

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

field.SetValue (..) для установки значения.

0 голосов
/ 27 мая 2009

Попробуйте использовать отражение. Вот простой код для достижения эффекта.

using System.Reflection;    

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

Теперь вы можете вызвать X, сначала получив FieldInfo для одного из полей в Bar.

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

FieldInfo fieldA = typeof(Bar).GetField("A");
int result = X(b, fieldA);
0 голосов
/ 27 мая 2009
public int X(Bar bar, string target)
{
    object value = bar.GetType().GetField(target, BindingFlags.Public | BindingFlags.Instance).GetValue(bar);
    return (int)value * 2;
}
0 голосов
/ 27 мая 2009

вы можете использовать класс PropertyInfo для получения нужного свойства с помощью отражения: https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-6099345.html

0 голосов
/ 27 мая 2009

Вы можете достичь этого, используя отражение. Это окажет некоторое влияние на производительность

...