简体   繁体   中英

Is it possible to pass in a property name as a string and assign a value to it?

I'm setting up a simple helper class to hold some data from a file I'm parsing. The names of the properties match the names of values that I expect to find in the file. I'd like to add a method called AddPropertyValue to my class so that I can assign a value to a property without explicitly calling it by name.

The method would look like this:

//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

The implementation might look like this:

C#/VB.NET

MyHelperClass.AddPropertyValue("LocationID","5")

Is this possible without having to test for each individual property name against the supplied propertyName ?

You can do this with reflection, by calling Type.GetProperty and then PropertyInfo.SetValue . You'll need to do appropriate error handling to check for the property not actually being present though.

Here's a sample:

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

If you need to do this a lot, it can become quite a pain in terms of performance. There are tricks around delegates which can make it a lot faster, but it's worth getting it working first.

Using reflection you get the property using the name and set its value... something like:

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

In terms of organizing the code, you could do it in a mixin-like way (error handling apart):

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

This way, you can reuse that logic in many different classes, without sacrificing your precious single base class with it.

In 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM