说我有以下课程:
class Person
{
public FirstType firstField ; // has a getter-setter
public SecondType secondField; // has a getter-setter
// more fields of other types
}
我想构建一个函数,接受Person
类作为其第一个参数,并将第一个参数字段之一的类型作为其第二个参数 - 假设{ {1}}的字段属于不同类型。
我的目标是能够对第二个参数使用反射,然后使用一些等效的点符号来访问传递的类。
Person
怎么做?
答案 0 :(得分:0)
可以使用反射轻松完成:您可以获取类型的所有公共属性,查找给定类型的公共属性,并在传递的person
实例的上下文中设置其值。
我还建议使用通用方法以获得更好的类型安全性和更简洁的用法:
public static void SetPersonField<T>(Person person, T value)
{
typeof (Person)
.GetProperties()
.Single(p => p.PropertyType == typeof(T))
.SetValue(person, value);
}
// Usage (both are correct):
SetPersonField(person, FirstType.EnumValue);
SetPersonField<FirstType>(person, FirstType.EnumValue);
您甚至不需要指定泛型类型,因为可以从输入参数中理解它。
请注意,如果此类型的无属性,或者此类型的多个属性,.Single
将引发异常。如果无法保证存在或唯一性,则需要使用SetPersonField
方法处理它
此外,请始终牢记使用反射时的巨大性能下降。
您可以实现更通用的方法,该方法将支持任何类型的属性和对象:
public static void SetField<TObject, TProperty>(TObject obj, TProperty value)
{
typeof(TObject)
.GetProperties()
.Single(p => p.PropertyType == typeof(TProperty))
.SetValue(obj, value);
}
var person = new Person();
SetField(person, 123); // finds the only int property and sets its value
SetField(person, FirstType.EnumValue); // find the only FirstType property
SetField<Person, DateTime?>(person, DateTime.Now); // finds the only DateTime? property
请注意,对于某些特定类型(f.i.,Nullable),您需要明确指定类型,因为无法从您的数据中理解它。
答案 1 :(得分:0)
我前段时间使用过这门课程
Public Class PropertySetter
Public Shared Sub SetObjectProperty(ByRef obj As Object, propertyInfo As PropertyInfo, propertyValue As Object)
'if we do not need to convert propertyValue to certain type
If IsNothing(propertyValue) OrElse propertyInfo.PropertyType = propertyValue.GetType() Then
obj.GetType().GetProperty(propertyInfo.Name).SetValue(obj, propertyValue)
Else
'Convert.ChangeType does not handle conversion to nullable types
'if the property type is nullable, we need to get the underlying type of the property
Dim targetType = If(IsNullableType(propertyInfo.PropertyType), Nullable.GetUnderlyingType(propertyInfo.PropertyType), propertyInfo.PropertyType)
'convert Enum
If (propertyValue.GetType() = GetType(String)) Then
If propertyInfo.PropertyType.IsEnum OrElse (Not Nullable.GetUnderlyingType(propertyInfo.PropertyType) Is Nothing AndAlso Nullable.GetUnderlyingType(propertyInfo.PropertyType).IsEnum) Then
'if propertyValue is equal to enum value
Try
propertyValue = [Enum].Parse(targetType, propertyValue.ToString())
Catch ex As Exception
'if propertyValue is equal to enum description
Dim enumValues = targetType.GetFields()
For Each enumValue In enumValues
Dim descriptionAttribute = enumValue.GetCustomAttribute(Of DescriptionAttribute)()
If Not descriptionAttribute Is Nothing Then
If (descriptionAttribute.Description.Trim().ToUpper() = propertyValue.ToString().ToUpper()) Then
propertyValue = enumValue.GetValue(Nothing)
Exit For
End If
End If
Next
End Try
End If
End If
'set object property via reflection
obj.GetType().GetProperty(propertyInfo.Name).SetValue(obj, Convert.ChangeType(propertyValue, targetType, CultureInfo.InvariantCulture))
End If
End Sub
Private Shared Function IsNullableType(type As Type) As Boolean
Return type.IsGenericType AndAlso type.GetGenericTypeDefinition().Equals(GetType(Nullable(Of )))
End Function
End Class
P.S。正如你所看到的vb.net。您可以使用this服务获取C#代码
答案 2 :(得分:0)
以下参考,以下是如何进行Getter查询:
public static object GetPersonField(Person person, Type fieldType)
{
return typeof (Person)
.GetProperties()
.Single(p => p.PropertyType == fieldType)
.GetValue(person);
}