【问题标题】:Is it possible to pass in a property name as a string and assign a value to it?是否可以将属性名称作为字符串传递并为其赋值?
【发布时间】:2010-08-09 18:51:51
【问题描述】:

我正在设置一个简单的帮助类来保存我正在解析的文件中的一些数据。属性的名称与我希望在文件中找到的值的名称相匹配。我想在我的类中添加一个名为 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 测试每个单独的属性名称?

【问题讨论】:

标签: c# .net vb.net reflection


【解决方案1】:

您可以通过调用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);
    }
}

如果您经常需要这样做,那么在性能方面可能会变得相当痛苦。委托有一些技巧可以使它更快,但值得先让它工作。

【讨论】:

    【解决方案2】:

    使用反射,您可以使用名称获取属性并设置其值...类似于:

    Type t = this.GetType();
    var prop = t.GetProperty(propName);
    prop.SetValue(this, value, null);
    

    【讨论】:

      【解决方案3】:

      在组织代码方面,您可以以mixin-like 的方式进行(错误处理除外):

      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
      

      【讨论】:

      • 对于get: public static string GetValue(this IPropertySettable self, string name) { return self.GetType().GetProperty(name).GetValue(self, null).ToString(); }
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 2012-06-05
      相关资源
      最近更新 更多