Я настраиваю простой класс помощника для содержания некоторых данных из файла, который я анализирую. Названия свойств соответствуют названиям значений, которые я ожидаю находить в файле. Я хотел бы добавить названный метод AddPropertyValue
к моему классу так, чтобы я мог присвоить значение свойству, явно не зовя его по имени.
Метод был бы похож на это:
//C#
public void AddPropertyValue(string propertyName, string propertyValue) {
//code to assign the property value based on propertyName
}
---
'VB.NET'
Public Sub AddPropertyValue(ByVal propertyName As String, _
ByVal propertyValue As String)
'code to assign the property value based on propertyName '
End Sub
Реализация могла бы быть похожей на это:
C#/VB.NET
MyHelperClass.AddPropertyValue("LocationID","5")
Это возможное, не имея необходимость тестировать на каждое отдельное имя свойства против предоставленного propertyName
?
Вы можете сделать это с помощью отражения, вызвав Type.GetProperty
, а затем PropertyInfo.SetValue
. Вам нужно будет выполнить соответствующую обработку ошибок, чтобы проверить, действительно ли свойство отсутствует.
Вот пример:
using System;
using System.Reflection;
public class Test
{
public string Foo { get; set; }
public string Bar { get; set; }
public void AddPropertyValue(string name, string value)
{
PropertyInfo property = typeof(Test).GetProperty(name);
if (property == null)
{
throw new ArgumentException("No such property!");
}
// More error checking here, around indexer parameters, property type,
// whether it's read-only etc
property.SetValue(this, value, null);
}
static void Main()
{
Test t = new Test();
t.AddPropertyValue("Foo", "hello");
t.AddPropertyValue("Bar", "world");
Console.WriteLine("{0} {1}", t.Foo, t.Bar);
}
}
Если вам нужно делать это много, это может стать проблемой с точки зрения производительности. Есть уловки с делегатами, которые могут сделать это намного быстрее, но сначала стоит заставить его работать.
Используя отражение, вы получаете свойство по имени и устанавливаете его значение... что-то вроде:
Type t = this.GetType();
var prop = t.GetProperty(propName);
prop.SetValue(this, value, null);
С точки зрения организации кода, вы можете сделать это миксиноподобным способом (отдельно от обработки ошибок):
public interface MPropertySettable { }
public static class PropertySettable {
public static void SetValue<T>(this MPropertySettable self, string name, T value) {
self.GetType().GetProperty(name).SetValue(self, value, null);
}
}
public class Foo : MPropertySettable {
public string Bar { get; set; }
public int Baz { get; set; }
}
class Program {
static void Main() {
var foo = new Foo();
foo.SetValue("Bar", "And the answer is");
foo.SetValue("Baz", 42);
Console.WriteLine("{0} {1}", foo.Bar, foo.Baz);
}
}
Таким образом, вы можете повторно использовать эту логику во многих разных классах, не жертвуя вместе с ним вашим драгоценным единственным базовым классом.
В VB.NET:
Public Interface MPropertySettable
End Interface
Public Module PropertySettable
<Extension()> _
Public Sub SetValue(Of T)(ByVal self As MPropertySettable, ByVal name As String, ByVal value As T)
self.GetType().GetProperty(name).SetValue(self, value, Nothing)
End Sub
End Module