我正在尝试在我的代码中实现使用反射进行数据转换的示例1。
GetSourceValue
函数有一个比较不同类型的switch语句,但我想删除这些类型和属性,并使GetSourceValue
仅使用单个字符串作为参数获取属性的值。我想要在字符串中传递类和属性,并解析属性的值。
这种做法可能吗?
我正在尝试在我的代码中实现使用反射进行数据转换的示例1。
GetSourceValue
函数有一个比较不同类型的switch语句,但我想删除这些类型和属性,并使GetSourceValue
仅使用单个字符串作为参数获取属性的值。我想要在字符串中传递类和属性,并解析属性的值。
这种做法可能吗?
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
当然,您肯定希望添加验证等功能,但这就是要点。
public static Object GetPropValue(this Object obj, String name) {
foreach (String part in name.Split('.')) {
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
public static T GetPropValue<T>(this Object obj, String name) {
Object retval = GetPropValue(obj, name);
if (retval == null) { return default(T); }
// throws InvalidCastException if types are incompatible
return (T) retval;
}
这将使您能够使用单个字符串进入属性,例如:
DateTime now = DateTime.Now;
int min = GetPropValue<int>(now, "TimeOfDay.Minutes");
int hrs = now.GetPropValue<int>("TimeOfDay.Hours");
您可以将这些方法作为静态方法或扩展方法使用。
PropertyInfo.PropertyType
而不是obj.GetType()
。 - Nulliusnameof
表达式,例如在调用函数时的名称参数上使用nameof(TimeOfDay.Minutes)
,以消除魔术字符串并为这些调用添加编译时安全性。 - Reap添加到任何类
中:
public class Foo
{
public object this[string propertyName]
{
get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
}
public string Bar { get; set; }
}
然后,您可以使用如下:
Foo f = new Foo();
// Set
f["Bar"] = "asdf";
// Get
string s = (string)f["Bar"];
使用Microsoft.VisualBasic
命名空间(Microsoft.VisualBasic.dll
)的CallByName
怎么样? 它使用反射来获取普通对象、COM对象甚至是动态对象的属性、字段和方法。
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
然后
Versioned.CallByName(this, "method/function/prop name", CallType.Get).ToString();
jheddings的好回答。我希望通过允许引用聚合的数组或对象集合来改进它,以便propertyName
可以是property1.property2[X].property3
:
public static object GetPropertyValue(object srcobj, string propertyName)
{
if (srcobj == null)
return null;
object obj = srcobj;
// Split property name to parts (propertyName could be hierarchical, like obj.subobj.subobj.property
string[] propertyNameParts = propertyName.Split('.');
foreach (string propertyNamePart in propertyNameParts)
{
if (obj == null) return null;
// propertyNamePart could contain reference to specific
// element (by index) inside a collection
if (!propertyNamePart.Contains("["))
{
PropertyInfo pi = obj.GetType().GetProperty(propertyNamePart);
if (pi == null) return null;
obj = pi.GetValue(obj, null);
}
else
{ // propertyNamePart is areference to specific element
// (by index) inside a collection
// like AggregatedCollection[123]
// get collection name and element index
int indexStart = propertyNamePart.IndexOf("[")+1;
string collectionPropertyName = propertyNamePart.Substring(0, indexStart-1);
int collectionElementIndex = Int32.Parse(propertyNamePart.Substring(indexStart, propertyNamePart.Length-indexStart-1));
// get collection object
PropertyInfo pi = obj.GetType().GetProperty(collectionPropertyName);
if (pi == null) return null;
object unknownCollection = pi.GetValue(obj, null);
// try to process the collection as array
if (unknownCollection.GetType().IsArray)
{
object[] collectionAsArray = unknownCollection as object[];
obj = collectionAsArray[collectionElementIndex];
}
else
{
// try to process the collection as IList
System.Collections.IList collectionAsList = unknownCollection as System.Collections.IList;
if (collectionAsList != null)
{
obj = collectionAsList[collectionElementIndex];
}
else
{
// ??? Unsupported collection type
}
}
}
}
return obj;
}
如果我使用Ed S.的代码,我会得到:
'ReflectionExtensions.GetProperty(Type, string)'由于其保护级别而无法访问。
看来Xamarin.Forms中不提供GetProperty()
方法。Profile7
是我的便携式类库(.NET Framework 4.5、Windows 8、ASP.NET Core 1.0、Xamarin.Android、Xamarin.iOS和Xamarin.iOS Classic)中的TargetFrameworkProfile
。
现在我找到了一个可行的解决方案:
using System.Linq;
using System.Reflection;
public static object GetPropValue(object source, string propertyName)
{
var property = source.GetType().GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, propertyName, StringComparison.OrdinalIgnoreCase));
return property?.GetValue(source);
}
return property?.GetValue(source);
- Tominoclass MyClass {
public string prop1 { set; get; }
public object this[string propertyName]
{
get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
}
}
获取属性值的方法如下:
MyClass t1 = new MyClass();
...
string value = t1["prop1"].ToString();
设置属性值:
t1["prop1"] = value;
.NET Standard中调用方法的方式已更改(从1.6版本开始)。此外,我们可以使用C# 6的null条件运算符。
using System.Reflection;
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetRuntimeProperty(propName)?.GetValue(src);
}
? 运算符
,准备好了吗? - blfuentesDataBinder.Eval Method (Object, String)
,则可以避免所有反射内容:var value = DataBinder.Eval(DateTime.Now, "TimeOfDay.Hours");
当然,你需要添加对System.Web
程序集的引用,但这可能并不是一个大问题。
public static List<KeyValuePair<string, string>> GetProperties(object item) //where T : class
{
var result = new List<KeyValuePair<string, string>>();
if (item != null)
{
var type = item.GetType();
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var pi in properties)
{
var selfValue = type.GetProperty(pi.Name).GetValue(item, null);
if (selfValue != null)
{
result.Add(new KeyValuePair<string, string>(pi.Name, selfValue.ToString()));
}
else
{
result.Add(new KeyValuePair<string, string>(pi.Name, null));
}
}
}
return result;
}
这是一种将所有属性及其值以列表形式获取的方法。
type.GetProperty(pi.Name)
,而不直接使用变量 pi
? - westonif
并执行selfValue?.ToString()
。否则,摆脱if
并使用selfValue==null?null:selfValue.ToString()
。 - westonList<KeyValuePair<
的列表很奇怪,那么请使用一个字典 Dictionary<string, string>
。 - weston
public static T GetPropertyValue<T>(object obj, string propName) { return (T)obj.GetType().GetProperty(propName).GetValue(obj, null); }
(该函数可以获取对象中指定属性的值,返回类型为 T) - Ohad Schneidersrc.GetType().GetProperty(propName)?.GetValue(src, null);
" ;)。 - shA.tGetProperty
中检查 null 并抛出PropertyNotFoundException
或类似的异常)。 - Ed S.GetField
而不是GetProperty
。 - Christopher K.