使用C#中的反射从字符串获取属性值
我正在尝试在代码中使用Reflection 1示例实现数据转换 。
GetSourceValue
函数具有比较各种类型的开关,但是我想删除这些类型和属性,并让GetSourceValue
仅使用单个字符串作为参数来获取属性的值。 我想在字符串中传递类和属性,并解析该属性的值。
这可能吗?
1个原始博客文章的Web存档版本
#1楼
public static object GetPropValue(object src, string propName){return src.GetType().GetProperty(propName).GetValue(src, null);}
当然,您将需要添加验证等功能,但这就是要点。
#2楼
这样的事情怎么样:
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 incompatiblereturn (T) retval;
}
这将允许您使用单个字符串进入属性,如下所示:
DateTime now = DateTime.Now;
int min = GetPropValue<int>(now, "TimeOfDay.Minutes");
int hrs = now.GetPropValue<int>("TimeOfDay.Hours");
您可以将这些方法用作静态方法或扩展。
#3楼
您永远不会提及要检查的对象,并且由于您拒绝引用给定对象的对象,因此我假设您的意思是静态对象。
using System.Reflection;
public object GetPropValue(string prop)
{int splitPoint = prop.LastIndexOf('.');Type type = Assembly.GetEntryAssembly().GetType(prop.Substring(0, splitPoint));object obj = null;return type.GetProperty(prop.Substring(splitPoint + 1)).GetValue(obj, null);
}
请注意,我用局部变量obj
标记了要检查的obj
。 null
表示静态,否则将其设置为所需的值。 还请注意, GetEntryAssembly()
是获取“运行中”程序集的几种可用方法之一,如果在加载类型时遇到困难,则可能需要使用它。
#4楼
使用Microsoft.VisualBasic
命名空间( Microsoft.VisualBasic.dll
)的CallByName
怎么办? 它使用反射来获取常规对象,COM对象甚至动态对象的属性,字段和方法。
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
然后
Versioned.CallByName(this, "method/function/prop name", CallType.Get).ToString();
#5楼
使用System.Reflection命名空间的PropertyInfo。 无论我们尝试访问什么属性,反射都可以编译。 该错误将在运行时出现。
public static object GetObjProperty(object obj, string property){Type t = obj.GetType();PropertyInfo p = t.GetProperty("Location");Point location = (Point)p.GetValue(obj, null);return location;}
获得对象的Location属性效果很好
Label1.Text = GetObjProperty(button1, "Location").ToString();
我们将获得Location:{X = 71,Y = 27}我们也可以以相同的方式返回location.X或location.Y。
#6楼
更短的方法....
var a = new Test { Id = 1 , Name = "A" , date = DateTime.Now};
var b = new Test { Id = 1 , Name = "AXXX", date = DateTime.Now };var compare = string.Join("",a.GetType().GetProperties().Select(x => x.GetValue(a)).ToArray())==string.Join("",b.GetType().GetProperties().Select(x => x.GetValue(b)).ToArray());
#7楼
添加到任何Class
:
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"];
#8楼
这是查找嵌套属性的另一种方法,该属性不需要字符串即可告诉您嵌套路径。 将单一属性方法归功于Ed S.。
public static T FindNestedPropertyValue<T, N>(N model, string propName) {T retVal = default(T);bool found = false;PropertyInfo[] properties = typeof(N).GetProperties();foreach (PropertyInfo property in properties) {var currentProperty = property.GetValue(model, null);if (!found) {try {retVal = GetPropValue<T>(currentProperty, propName);found = true;} catch { }}}if (!found) {throw new Exception("Unable to find property: " + propName);}return retVal;}public static T GetPropValue<T>(object srcObject, string propName) {return (T)srcObject.GetType().GetProperty(propName).GetValue(srcObject, null);}
#9楼
以下代码是一种递归方法,用于显示对象实例中包含的所有属性名称和值的整个层次结构。 此方法在该线程中使用上面的AlexD的GetPropertyValue()
答案的简化版本。 由于有了这个讨论线程,我得以弄清楚该如何做!
例如,通过使用如下方法,我使用此方法来显示WebService
响应中所有属性的爆炸或转储:
PropertyValues_byRecursion("Response", response, false);
public static object GetPropertyValue(object srcObj, string propertyName)
{if (srcObj == null) {return null; }PropertyInfo pi = srcObj.GetType().GetProperty(propertyName.Replace("[]", ""));if (pi == null){return null;}return pi.GetValue(srcObj);
}public static void PropertyValues_byRecursion(string parentPath, object parentObj, bool showNullValues)
{/// Processes all of the objects contained in the parent object./// If an object has a Property Value, then the value is written to the Console/// Else if the object is a container, then this method is called recursively/// using the current path and current object as parameters// Note: If you do not want to see null values, set showNullValues = falseforeach (PropertyInfo pi in parentObj.GetType().GetTypeInfo().GetProperties()){// Build the current object property's namespace path. // Recursion extends this to be the property's full namespace path.string currentPath = parentPath + "." + pi.Name;// Get the selected property's value as an objectobject myPropertyValue = GetPropertyValue(parentObj, pi.Name);if (myPropertyValue == null){// Instance of Property does not existif (showNullValues){Console.WriteLine(currentPath + " = null");// Note: If you are replacing these Console.Write... methods callback methods,// consider passing DBNull.Value instead of null in any method object parameters.}}else if (myPropertyValue.GetType().IsArray){// myPropertyValue is an object instance of an Array of business objects.// Initialize an array index variable so we can show NamespacePath[idx] in the results.int idx = 0;foreach (object business in (Array)myPropertyValue){if (business == null){// Instance of Property does not exist// Not sure if this is possible in this context.if (showNullValues){Console.WriteLine(currentPath + "[" + idx.ToString() + "]" + " = null");}}else if (business.GetType().IsArray){// myPropertyValue[idx] is another Array!// Let recursion process it.PropertyValues_byRecursion(currentPath + "[" + idx.ToString() + "]", business, showNullValues);}else if (business.GetType().IsSealed){// Display the Full Property Path and its ValueConsole.WriteLine(currentPath + "[" + idx.ToString() + "] = " + business.ToString());}else{// Unsealed Type Properties can contain child objects.// Recurse into my property value object to process its properties and child objects.PropertyValues_byRecursion(currentPath + "[" + idx.ToString() + "]", business, showNullValues);}idx++;}}else if (myPropertyValue.GetType().IsSealed){// myPropertyValue is a simple valueConsole.WriteLine(currentPath + " = " + myPropertyValue.ToString());}else{// Unsealed Type Properties can contain child objects.// Recurse into my property value object to process its properties and child objects.PropertyValues_byRecursion(currentPath, myPropertyValue, showNullValues);}}
}
#10楼
Dim NewHandle As YourType = CType(Microsoft.VisualBasic.CallByName(ObjectThatContainsYourVariable, "YourVariableName", CallType), YourType)
#11楼
关于嵌套属性的讨论,如果使用如下所示的DataBinder.Eval Method (Object, String)
,则可以避免所有反射:
var value = DataBinder.Eval(DateTime.Now, "TimeOfDay.Hours");
当然,您需要添加对System.Web
程序集的引用,但这可能没什么大不了的。
#12楼
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;}
这是一种在列表中获取所有属性及其值的方法。
#13楼
jheddings和AlexD都就如何解析属性字符串写了出色的答案。 我想把我的东西混在一起,因为我正是为此目的编写了一个专用的库。
Pather.CSharp的主要类是Resolver
。 默认情况下,它可以解析属性,数组和字典条目。
因此,例如,如果您有一个像这样的对象
var o = new { Property1 = new { Property2 = "value" } };
并想要获取Property2
,您可以这样:
IResolver resolver = new Resolver();
var path = "Property1.Property2";
object result = r.Resolve(o, path);
//=> "value"
这是它可以解析的路径的最基本示例。 如果您想了解它的其他功能或扩展方法,请转到Github页面 。
#14楼
如果我使用Ed S的代码,我会得到
“ ReflectionExtensions.GetProperty(Type,string)”由于其保护级别而无法访问
似乎Xamarin.Forms中没有GetProperty()
。 TargetFrameworkProfile
是Profile7
在我的便携式类库(.NET框架4.5,Windows 8中,ASP.NET 1.0的核心,Xamarin.Android,Xamarin.iOS,Xamarin.iOS经典)。
现在我找到了一个可行的解决方案:
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);
}
资源
#15楼
调用方法已在.NET Standard(自1.6版)中更改。 我们也可以使用C#6的空条件运算符。
using System.Reflection;
public static object GetPropValue(object src, string propName)
{return src.GetType().GetRuntimeProperty(propName)?.GetValue(src);
}
#16楼
public static TValue GetFieldValue<TValue>(this object instance, string name)
{var type = instance.GetType(); var field = type.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).FirstOrDefault(e => typeof(TValue).IsAssignableFrom(e.FieldType) && e.Name == name);return (TValue)field?.GetValue(instance);
}public static TValue GetPropertyValue<TValue>(this object instance, string name)
{var type = instance.GetType();var field = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).FirstOrDefault(e => typeof(TValue).IsAssignableFrom(e.PropertyType) && e.Name == name);return (TValue)field?.GetValue(instance);
}
#17楼
这是我的解决方案。 它也可以与COM对象一起使用,并允许从COM对象访问集合/数组项。
public static object GetPropValue(this object obj, string name)
{foreach (string part in name.Split('.')){if (obj == null) { return null; }Type type = obj.GetType();if (type.Name == "__ComObject"){if (part.Contains('[')){string partWithoundIndex = part;int index = ParseIndexFromPropertyName(ref partWithoundIndex);obj = Versioned.CallByName(obj, partWithoundIndex, CallType.Get, index);}else{obj = Versioned.CallByName(obj, part, CallType.Get);}}else{PropertyInfo info = type.GetProperty(part);if (info == null) { return null; }obj = info.GetValue(obj, null);}}return obj;
}private static int ParseIndexFromPropertyName(ref string name)
{int index = -1;int s = name.IndexOf('[') + 1;int e = name.IndexOf(']');if (e < s){throw new ArgumentException();}string tmp = name.Substring(s, e - s);index = Convert.ToInt32(tmp);name = name.Substring(0, s - 1);return index;
}
#18楼
public class YourClass
{//Add below line in your classpublic object this[string propertyName] => GetType().GetProperty(propertyName)?.GetValue(this, null);public string SampleProperty { get; set; }
}//And you can get value of any property like this.
var value = YourClass["SampleProperty"];
#19楼
以下方法最适合我:
class 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;
#20楼
看看Heleonix.Reflection库。 您可以通过路径获取/设置/调用成员,或者创建比反射更快的getter / setter(lambda编译为委托)。 例如:
var success = Reflector.Get(DateTime.Now, null, "Date.Year", out int value);
或一次创建一个吸气剂并缓存以备重用(这具有更高的性能,但如果中间成员为null,则可能会抛出NullReferenceException):
var getter = Reflector.CreateGetter<DateTime, int>("Date.Year", typeof(DateTime));
getter(DateTime.Now);
或者,如果您要创建具有不同getter的List<Action<object, object>>
,只需为编译的委托指定基本类型(类型转换将添加到编译的lambda中):
var getter = Reflector.CreateGetter<object, object>("Date.Year", typeof(DateTime));
getter(DateTime.Now);
#21楼
这是我根据其他答案得到的。 在错误处理方面变得如此具体有些过大的杀伤力。
public static T GetPropertyValue<T>(object sourceInstance, string targetPropertyName, bool throwExceptionIfNotExists = false)
{string errorMsg = null;try{if (sourceInstance == null || string.IsNullOrWhiteSpace(targetPropertyName)){errorMsg = $"Source object is null or property name is null or whitespace. '{targetPropertyName}'";Log.Warn(errorMsg);if (throwExceptionIfNotExists)throw new ArgumentException(errorMsg);elsereturn default(T);}Type returnType = typeof(T);Type sourceType = sourceInstance.GetType();PropertyInfo propertyInfo = sourceType.GetProperty(targetPropertyName, returnType);if (propertyInfo == null){errorMsg = $"Property name '{targetPropertyName}' of type '{returnType}' not found for source object of type '{sourceType}'";Log.Warn(errorMsg);if (throwExceptionIfNotExists)throw new ArgumentException(errorMsg);elsereturn default(T);}return (T)propertyInfo.GetValue(sourceInstance, null);}catch(Exception ex){errorMsg = $"Problem getting property name '{targetPropertyName}' from source instance.";Log.Error(errorMsg, ex);if (throwExceptionIfNotExists)throw;}return default(T);
}
#22楼
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.propertystring[] propertyNameParts = propertyName.Split('.');foreach (string propertyNamePart in propertyNameParts){if (obj == null) return null;// propertyNamePart could contain reference to specific // element (by index) inside a collectionif (!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 indexint indexStart = propertyNamePart.IndexOf("[")+1;string collectionPropertyName = propertyNamePart.Substring(0, indexStart-1);int collectionElementIndex = Int32.Parse(propertyNamePart.Substring(indexStart, propertyNamePart.Length-indexStart-1));// get collection objectPropertyInfo pi = obj.GetType().GetProperty(collectionPropertyName);if (pi == null) return null;object unknownCollection = pi.GetValue(obj, null);// try to process the collection as arrayif (unknownCollection.GetType().IsArray){object[] collectionAsArray = unknownCollection as object[];obj = collectionAsArray[collectionElementIndex];}else{// try to process the collection as IListSystem.Collections.IList collectionAsList = unknownCollection as System.Collections.IList;if (collectionAsList != null){obj = collectionAsList[collectionElementIndex];}else{// ??? Unsupported collection type}}}}return obj;}
使用C#中的反射从字符串获取属性值相关推荐
- Spring Boot 项目中Java对象的字符串类型属性值转换为JSON对象的布尔类型键值的解决方法及过程
文章目录 场景描述 示例说明 解决历程 @JsonFormat是否能解决问题? 万能方案-调试 替代方案 补充知识 Java对象与JSON对象的序列化与反序列化 相关注解说明 后记 场景描述 在Spr ...
- java8 方法引用详解_Java8中如何通过方法引用获取属性名详解
前言 在我们开发过程中常常有一个需求,就是要知道实体类中Getter方法对应的属性名称(Field Name),例如实体类属性到数据库字段的映射,我们常常是硬编码指定 属性名,这种硬编码有两个缺点. ...
- struts2原理分析之反射技术动态获取属性
反射技术动态获取属性 知道struts2的流程的乡亲们都知道.struts2采用了动态获取属性的方法, 将表单里的数据传给了Action. 例如; 在struts2里有如下配置文件 <actio ...
- java 反射根据属性名获取属性值
一.背景 在使用三方sdk的时候如果三方提供的api满足不了我们的需求,这时候就需要通过阅读三方sdk的代码,并通过反射来实现我们的需求. 二.根据属性名获取属性值 1.考虑安全访问范围内的属性,没有 ...
- java 操作属性值_java反射机制根据属性名获取属性值的操作
一.考虑安全访问范围内的属性,没有权限访问到的属性不读取 /** * 根据属性名获取属性值 * * @param fieldName * @param object * @return */ priv ...
- java中遍历实体类,获取属性名和属性值
方式一(实体类): //java中遍历实体类,获取属性名和属性值public static void testReflect(Object model) throws Exception{for (F ...
- java通过属性名获取属性值_java反射机制根据属性名获取属性值的操作
java反射机制根据属性名获取属性值的操作,属性,对象,反射,访问权限,还可以 java反射机制根据属性名获取属性值的操作 易采站长站,站长之家为您整理了java反射机制根据属性名获取属性值的操作的相 ...
- java 反射机制--根据属性名获取属性值
1.考虑安全访问范围内的属性,没有权限访问到的属性不读取 [java] view plaincopy /** * 根据属性名获取属性值 * * @param fieldName * @param ob ...
- java dom4 引入_java – 使用dom4j从节点获取属性值
我的 XML结构类似于下面的示例.我正在尝试使用dom4j从XML中获取属性值. 目前,节点使用以下代码存储到List中: public List getFoo() { String FOO_XPAT ...
最新文章
- error 图片,加载错误-》实用笔记
- java三大集合_java中三大集合框架
- python3 计时性能测试 %timeit %%timeit
- could not insert into NHibernate数据库问题解决
- c 用mysql导出xls文件怎么打开_mysql——xls表格的导出和导入(重点)
- 在印度8年的华为工程师,有很多话想说。
- 手把手教你全家桶之React(一)
- 【操作系统】多线程与多任务的比较
- 续昨天的文章,在火山图标记基因名字
- 为 ASP.NET 创建缓存配置对象[转载]
- Web---演示Servlet的相关类、下载技术、线程问题、自定义404页面
- 绝对路径、相对路径详解
- 航空公司VIP客户查询
- 269个JavaScript工具函数,助你提升工作效率(2)
- 国内景色最震撼的9座雪山
- 终于稀里糊涂完成了模仿天猫整站ssm
- Mezzanine入门
- CSV文件批量合并/转XLSX(无需任何软件,傻瓜式操作)
- STM32F103实现激光测距传感器测距WT-VL53L0 L1
- 提高安卓源码编译速度