2012-04-22 2 views
0

Это интересная концепция, которую я не мог понять, как реализовать. (это связано с присвоением университета, когда мне нужно развернуть шаблон декоратора).Применение функции для каждого поля в классе

Я написал грубый C# код, ниже которого не будет компилировать Однако предположим, что, у меня есть класс

Class A { 
    public int A { get; set; } 
    public string B { get; set; } 
    public float C { get; set; } 

    public string concatFields() { 
     string sample = null; 
     foreach (Field f in this) { 
      sample += f.ToString(); 
     } 
     return sample; 
    } 
} 

Как с точки зрения вы бы достичь метода concatFields? Есть ли способ выполнить итерацию полей класса (не зная имена полей) и вызвать ToString() для каждого из них.

В примере B сценарий, как бы вы применили тот же метод для всех полей, если они были того же типа.

Приветствия ребята за помощь, я уже помечено это с C#, но не уверен, что другие теги могут быть применены

+1

Концепция, которую вы ищете, называется «Отражение» –

+0

Пожалуйста, посмотрите этот пример на [dotnetpearls] (http://www.dotnetperls.com/reflection-field), он дает довольно простой пример (с кодом), который делает именно то, что вы просите использовать отражение. – vpiTriumph

ответ

1

Вы можете использовать reflection, перебрать метаданные вашего класса, и тянуть поля через Reflection API. Очевидно, что к этому относятся затраты: использование отражения происходит медленнее, чем прямой доступ к полям; иногда, значительно. Однако вы можете это сделать. Вот пример:

MyClass obj = new MyClass(); 
// Set fields in the obj... 
var fields = typeof(MyClass).GetFields(System.Reflection.BindingFlags.GetField); 
StringBuilder res = new StringBuilder(); 
foreach (FieldInfo f in fields) { 
    var val = f.GetValue(obj); 
    if (val != null) res.Append(val.ToString()); 
} 
Console.WriteLine(res.ToString()); 

FieldInfo класс предоставляет множество полезных свойств, таких как Name и Type, что позволяет выбрать, какие поля нужно включить в обработку, а также поля, чтобы их игнорировать.

+0

Очень важно использовать '.GetFields (System.Reflection.BindingFlags.GetField)' или вы получите исключение, пытаясь прочитать поле без геттера. –

+0

@ErikPhilips Спасибо за важное замечание! В качестве побочного примечания, если вы видите 100% -ное изменение, подобное этому, не стесняйтесь редактировать ответ: если автору не нравится изменение, он или она всегда может отменить свои изменения. Еще раз спасибо! – dasblinkenlight

0

Для .NET/C#, тип introspection обрабатывается через пространство имен System.Reflection. Это позволяет вам получать информацию о типах и динамически вызывать методы, неизвестные во время компиляции.

Как в плане вы могли бы использовать метод concatFields? Есть ли способ выполнить итерацию полей класса (не зная имена полей) и вызвать ToString() для каждого из них.

public string concatFields() { 
    string sample = null; // a StringBuilder would be a better choice here 
    foreach (FieldInfo f in this.GetType().GetFields()) { 
     obj fieldValue = f.GetValue(); 
     if (fieldValue != null) sample += fieldValue.ToString(); 
    } 
    return sample; 
} 

В сценарии примера B, как бы вы применить тот же метод на всех полях при условии, что они были того же типа.

Если вы знаете тип во время компиляции, вы можете бросить на него:

foreach (FieldInfo f in this.GetType().GetFields()) { 
    MyType myType = (MyType)f.GetValue(); 
    myType.MyMethod(); 
} 

Или, вы можете динамически вызывать с помощью отражения:

foreach (FieldInfo f in this.GetType().GetFields()) { 
    object fieldValue = f.GetValue(); 
    MethodInfo mi = fieldValue.GetType().GetMethod("MyMethod"); 
    mi.Invoke(fieldValue, null); // no parameters to MyMethod 
} 
0

Это, как я хотел бы сделать это:

class A 

{ 
    public int A { get; set; } 
    public string B { get; set; } 
    public float C { get; set; } 

    public string[] concatFields() 
    { 
     var v = from f in this.GetType().GetFields() select f; 
     IList<string> fields = new List<string>(); 
     foreach (var f in v) 
     { 
      fields.Add(f.GetValue(this).ToString()); 
     } 
     return fields.ToArray<string>(); 
    } 
} 
Смежные вопросы