我需要遍历项目的所有String
属性,检索它们的值,并操纵这些值-无需知道该项目的名称或属性本身。到目前为止,我所见过的所有SetValue
示例都假设您知道属性的名称,并使用该名称来引用它。就我而言,我没有按名称调用任何东西,而是简单地遍历每个字符串。
public class SpecialClass
{
public string MyString1 { get; set; }
public string MyString2 { get; set; }
public void Sanitize()
{
Type CheckItemType = typeof(SpecialClass);
Type strType = typeof(System.String);
PropertyInfo[] propInfos = CheckItemType.GetProperties(
BindingFlags.Public | BindingFlags.Instance);
foreach (var propInfo in propInfos)
{
if (null != propInfo && propInfo.CanWrite)
{
if (propInfo.PropertyType == typeof(System.String))
{
// Retrieve the value of the string, manipulate, and then set it
}
}
}
}
}
在上面的代码中,Sanitize
方法将遍历类中的字符串,并在满足特定条件的情况下调整其值。
当我找到this post时,它描述的内容似乎要求您知道项目和属性的名称。就我而言,我也不知道。我有一个Method的目的是执行String
类型的所有属性的操作。
我不能做this,因为我在对象内部进行内部工作-不在外部进行引用-因此我看不到它怎么工作。
直觉上我认为这应该是可能的,但是我不能完全理解它的语法。
一种替代方法是将其创建为ref
对象的独立函数,并且它执行相同类型的操作,除了在这种情况下该对象将具有名称。
答案 0 :(得分:2)
我建议使用 Linq 以便进行查询类型并获得所需的属性:
var properties = GetType() // current type
.GetProperties(BindingFlags.Public | BindingFlags.Instance) // public, not static
.Where(p => p.CanRead && p.CanWrite) // can read and write
.Where(p => !p.GetIndexParameters().Any()) // not indexer
.Where(p => p.PropertyType == typeof(string)); // of type string
然后在foreach
循环中分析这些属性及其值,如下所示:
using System.Linq;
using System.Reflection;
...
public void Sanitize() {
var properties = GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanRead && p.CanWrite)
.Where(p => !p.GetIndexParameters().Any())
.Where(p => p.PropertyType == typeof(string));
foreach (PropertyInfo prop in properties) {
// just for reference: if you want to include static properties
// you'll have to put null as instance
object target = prop.GetGetMethod().IsStatic ? null : this;
// current property value
string value = prop.GetValue(target) as String;
//ToDo: Put relevant code here
string someModifiedValue = value + "_modified";
// Write, if required
prop.SetValue(target, someModifiedValue);
}
}
答案 1 :(得分:1)
找到属性后,您可以编写:
string value = (string)propInfo.GetValue(this);
// manipulate
propInfo.SetValue(this, value);
因此方法可以是:
public void Sanitize()
{
var CheckItemType = typeof(SpecialClass);
var strType = typeof(string);
var propInfos = CheckItemType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach ( var propInfo in propInfos )
if ( propInfo.PropertyType == strType && propInfo.CanWrite )
{
string value = (string)propInfo.GetValue(this);
// manipulate
propInfo.SetValue(this, value);
}
}
您也可以使用Linq:
public void Sanitize()
{
var typeString = typeof(string);
var propertiesInfos = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeString
&& p.CanWrite
&& p.CanRead);
foreach ( var propertyInfo in propertiesInfos )
{
string value = (string)propertyInfo.GetValue(this);
// manipulate
propertyInfo.SetValue(this, value);
}
}
我们在这里解析实例(此)属性,而不是静态的...因此,您可以看到@DmitryBychenko答案来考虑它们,并通过添加{{1来对静态成员使用null
而不是this
}},以根据需要选择它们。
答案 2 :(得分:0)
我会做这样的事情。
SpecialClass sc = new SpecialClass()
{
MyString1 = "abc",
MyString2 = "xyz"
};
Sanitize(sc);
还有消毒方法。
public void Sanitize(object obj)
{
//loop all the propterties
foreach (PropertyInfo propInfo in obj.GetType().GetProperties())
{
//check if the property is a string
if (propInfo.PropertyType != typeof(System.String))
continue;
//get the value
string value = (string)propInfo.GetValue(obj, null);
value = value + "_TEST";
//set the value
propInfo.SetValue(obj, value);
}
}