Let's say I have a class that has 3 properties. I don't know which property I want to read until runtime. Is there a way to do this without a switch/if-else statement?
If a DataTable is treated as a class, then the columns can be treated dynamically which would work, but I'm not able to change my class into a DataTable (long story).
For a DataTable, the code would be:
string colu开发者_C百科mnName = "Age";
int age = dataRow[columnName];
How is this possible in a class?
string propertyName = "Baka";
int age = item.getProperty(propertyName) // ???
The easiest way to do this kind of runtime evaluation is with Reflection.
Depending on the version of .NET you're using, you could add methods to your class or use extension methods.
EDIT: I just read your comment about not using a switch, but I'll keep this here anyway, just in case... skip to my second answer.
Maybe something like this:
public enum Property { Name, Age, DateOfBirth};
public T GetProperty<T>(Property property)
{
switch (property)
{
case Property.Name:
return this.Name;
// etc.
}
}
I'm not too strong in Genetics, so maybe someone can help me with the return cast.
Alternatively, you could add a field to your class of type DataRow and use an indexer to access it:
public class MyClass
{
DataTable myRow = null;
MyClass(DataRow row)
{
myRow = row;
}
public object this[string name]
{
get
{
return this.myRow[name];
}
set
{
this.myRow[name] = value;
}
}
}
Usage:
MyClass c = new MyClass(table.Rows[0]);
string name = c["Name"].ToString();
Answered a similar question earlier. Here's a code sample, and link to the other question. Hiding Public Functions
You're going to be most interested in the GetValue method of the System.Reflection.PropertyInfo class.
C# Code Sample
public bool SetProperty(object obj, string PropertyName, object val)
{
object property_value = null;
System.Reflection.PropertyInfo[] properties_info = obj.GetType.GetProperties;
System.Reflection.PropertyInfo property_info = default(System.Reflection.PropertyInfo);
foreach (System.Reflection.PropertyInfo prop in properties_info) {
if (prop.Name == PropertyName) property_info = prop;
}
if (property_info != null) {
try {
property_info.SetValue(obj, val, null);
return true;
}
catch (Exception ex) {
return false;
}
}
else {
return false;
}
}
public object GetProperty(object obj, string PropertyName)
{
object property_value = null;
System.Reflection.PropertyInfo[] properties_info = obj.GetType.GetProperties;
System.Reflection.PropertyInfo property_info = default(System.Reflection.PropertyInfo);
foreach (System.Reflection.PropertyInfo prop in properties_info) {
if (prop.Name == PropertyName) property_info = prop;
}
if (property_info != null) {
try {
property_value = property_info.GetValue(obj, null);
return property_value;
}
catch (Exception ex) {
return null;
}
}
else {
return null;
}
}
VB Code Sample
Public Function SetProperty(ByVal obj As Object, ByVal PropertyName As String, ByVal val As Object) As Boolean
Dim property_value As Object
Dim properties_info As System.Reflection.PropertyInfo() = obj.GetType.GetProperties
Dim property_info As System.Reflection.PropertyInfo
For Each prop As System.Reflection.PropertyInfo In properties_info
If prop.Name = PropertyName Then property_info = prop
Next
If property_info IsNot Nothing Then
Try
property_info.SetValue(obj, val, Nothing)
Return True
Catch ex As Exception
Return False
End Try
Else
Return False
End If
End Function
Public Function GetProperty(ByVal obj As Object, ByVal PropertyName As String) As Object
Dim property_value As Object
Dim properties_info As System.Reflection.PropertyInfo() = obj.GetType.GetProperties
Dim property_info As System.Reflection.PropertyInfo
For Each prop As System.Reflection.PropertyInfo In properties_info
If prop.Name = PropertyName Then property_info = prop
Next
If property_info IsNot Nothing Then
Try
property_value = property_info.GetValue(obj, Nothing)
Return property_value
Catch ex As Exception
Return Nothing
End Try
Else
Return Nothing
End If
End Function
If you know the type of object you can get all the properties, and then your requested property, using reflection.
MyClass o;
PropertyInfo[] properties = o.GetType().GetProperties(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
Each PropertyInfo has a Name which you can match up to your String.
item.GetProperties() would return a PropertyInfo[] containing all properties (public only I think)
A PropertyInfo Object has a property Name which is the name of the property, so you can iterate over the array searching for a PropertyInfo object with your search name.
string propertyToGet = "SomeProperty";
SomeClass anObject = new SomeClass();
string propertyValue =
(string)typeof(SomeClass)
.GetProperty("SomeProperty")
.GetValue(anObject, null);
Example using indexers:
public class MyItem
{
public object this[string name]
{
switch (name)
{
case "Name":
return "Wikipetan";
case "Age":
return 8;
case "DateOfBirth":
return new DateTime(2001, 01, 15);
case "Baka":
return false;
default:
throw new ArgumentException();
}
}
}
Usage:
MyItem item = ...;
string propertyName = "Age";
int age = (int)item[propertyName];
精彩评论