C# 修剪所有字符串属性
我需要修剪对象中的一些字符串属性,但我不想转到所有对象和属性,在设置属性中执行修剪方法(有很多对象、300+和很多字符串属性) 提示:我的所有对象都有一个名为CoreTransaction的超类,因此我可以使用它(通过某种反射)更轻松地完成这项工作C# 修剪所有字符串属性,c#,reflection,C#,Reflection,我需要修剪对象中的一些字符串属性,但我不想转到所有对象和属性,在设置属性中执行修剪方法(有很多对象、300+和很多字符串属性) 提示:我的所有对象都有一个名为CoreTransaction的超类,因此我可以使用它(通过某种反射)更轻松地完成这项工作 这可能吗?您可以使用反射来执行以下操作: var stringProperties = obj.GetType().GetProperties() .Where(p => p.Property
这可能吗?您可以使用反射来执行以下操作:
var stringProperties = obj.GetType().GetProperties()
.Where(p => p.PropertyType == typeof (string));
foreach (var stringProperty in stringProperties)
{
string currentValue = (string) stringProperty.GetValue(obj, null);
stringProperty.SetValue(obj, currentValue.Trim(), null) ;
}
// o is your instance object
List<PropertyInfo> fields = o.GetType().GetProperties()
.Where(i => i.PropertyType == typeof(string));
fields.ForEach(i => i.SetValue(o, ((string)i.GetValue(o, null)).Trim(), new object[]{}));
//o是您的实例对象
列表字段=o.GetType().GetProperties()
。其中(i=>i.PropertyType==typeof(string));
fields.ForEach(i=>i.SetValue(o,((string)i.GetValue(o,null)).Trim(),新对象[]{});
我不确定是否要更改访问者的行为。听起来一点也不容易。将修剪添加到基类中如何
class CoreTransaction
{
public void Trim()
{
IEnumerable<PropertyInfo> stringProperties =
this.GetType().GetProperties()
.Where(p => p.PropertyType == typeof(string) && p.CanRead && p.CanWrite);
foreach (PropertyInfo property in stringProperties)
{
string value = (string)property.GetValue(this, null);
value = value.Trim();
property.SetValue(this, value, null);
}
}
}
类核心事务
{
公共空间修剪()
{
IEnumerable属性=
此.GetType().GetProperties()
其中(p=>p.PropertyType==typeof(string)和&p.CanRead和&p.CanWrite);
foreach(stringProperties中的PropertyInfo属性)
{
string value=(string)property.GetValue(this,null);
value=value.Trim();
SetValue(this,value,null);
}
}
}
(另外,请注意检查字段是否可以读取和写入。)
编辑:然后您可以向基类中添加类似的内容,并一次性修剪所有这些内容。
WeakReference类将允许您轻松跟踪实例,而不会妨碍垃圾收集器:
class CoreTransaction
{
private static List<WeakReference> allCoreTransactions = new List<WeakReference>();
public CoreTransaction()
{
allCoreTransactions.Add(new WeakReference(this));
}
public static void TrimAll()
{
foreach (WeakReference reference in allCoreTransactions)
{
if (reference.IsAlive)
{
((CoreTransaction)reference.Target).Trim();
}
}
}
}
类核心事务
{
私有静态列表allCoreTransactions=新列表();
公共事务()
{
添加(新WeakReference(this));
}
公共静态void TrimAll()
{
foreach(allCoreTransactions中的WeakReference引用)
{
如果(reference.IsAlive)
{
((coretransation)reference.Target).Trim();
}
}
}
}
感谢您为OP问题提供的解决方案。我将您的解决方案转换为扩展方法,并修复了空值抛出错误的问题
/// <summary>Trim all String properties of the given object</summary>
public static TSelf TrimStringProperties<TSelf>(this TSelf input)
{
var stringProperties = input.GetType().GetProperties()
.Where(p => p.PropertyType == typeof(string) && p.CanWrite);
foreach (var stringProperty in stringProperties)
{
string currentValue = (string)stringProperty.GetValue(input, null);
if (currentValue != null)
stringProperty.SetValue(input, currentValue.Trim(), null);
}
return input;
}
///修剪给定对象的所有字符串属性
公共静态TSelf TrimStringProperties(此TSelf输入)
{
var stringProperties=input.GetType().GetProperties()
其中(p=>p.PropertyType==typeof(string)和&p.CanWrite);
foreach(stringProperties中的var stringProperty)
{
string currentValue=(string)stringProperty.GetValue(输入,null);
if(currentValue!=null)
SetValue(输入,currentValue.Trim(),null);
}
返回输入;
}
对于那些使用VB.NET的人,我转换了Tharwnis的答案,并添加了一个条件,只返回那些非只读的属性。否则,如果类具有只读属性,则在尝试设置这些属性的值时将出现运行时错误
''' <summary>
''' Trim all NOT ReadOnly String properties of the given object
''' </summary>
<Extension()>
Public Function TrimStringProperties(Of T)(ByVal input As T) As T
Dim stringProperties = input.GetType().GetProperties().Where(Function(p) p.PropertyType = GetType(String) AndAlso p.CanWrite)
For Each stringProperty In stringProperties
Dim currentValue As String = Convert.ToString(stringProperty.GetValue(input, Nothing))
If currentValue IsNot Nothing Then
stringProperty.SetValue(input, currentValue.Trim(), Nothing)
End If
Next
Return input
End Function
“”
''修剪给定对象的所有非只读字符串属性
'''
公共函数TrimStringProperties(Of T)(ByVal输入为T)作为T
Dim stringProperties=input.GetType().GetProperties().Where(函数(p)p.PropertyType=GetType(字符串)并同时执行p.CanWrite)
对于stringProperties中的每个stringProperty
Dim currentValue As String=Convert.ToString(stringProperty.GetValue(输入,无))
如果currentValue不是Nothing,则
stringProperty.SetValue(输入,currentValue.Trim(),无)
如果结束
下一个
返回输入
端函数
您可以尝试:
static public class Trim<T>
where T : class
{
static public readonly Action<T> TrimAllStringFields = Trim<T>.CreateTrimAllStringFields();
static private Action<T> CreatTrimAllStringFields()
{
var instance = Expression.Parameter(typeof(T));
return Expression.Lambda<Action<T>>(Expression.Block(instance.Type.GetFields(BindingsFlags.Instance| BindingFlags.NonPublic | BindingFlags.Public).Select(field => Expression.Assign(Expression.Field(instance, field)) as Expression), instance).Compile();
}
}
静态公共类修剪
T:在哪里上课
{
静态公共只读操作TrimAllStringFields=Trim.CreateTrimAllStringFields();
静态私有操作CreatTrimAllStringFields()
{
var instance=Expression.Parameter(typeof(T));
返回Expression.Lambda(Expression.Block(instance.Type.GetFields(BindingsFlags.instance | BindingFlags.NonPublic | BindingFlags.Public)。选择(field=>Expression.Assign(Expression.field(instance,field))作为表达式),instance.Compile();
}
}
像这样使用它:
var myinstance = new MyClass();
Trim<MyClass>.TrimAllStringFields(myinstance);
var myinstance=new MyClass();
Trim.TrimAllStringFields(myinstance);
我编写了一个扩展方法,该方法还负责引用类(如parent.Child.Name)上的子类和字符串
公共静态类扩展方法
{
公共静态void TrimAllStrings(此TSelf对象)
{
BindingFlags flags=BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlatterHierarchy;
foreach(obj.GetType().GetProperties(标志)中的PropertyInfo p)
{
类型currentNodeType=p.PropertyType;
if(currentNodeType==typeof(String))
{
字符串currentValue=(字符串)p.GetValue(obj,null);
if(currentValue!=null)
{
p、 SetValue(obj,currentValue.Trim(),null);
}
}
//看http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection
else if(currentNodeType!=typeof(object)&&Type.GetTypeCode(currentNodeType)==TypeCode.object)
{
p、 GetValue(obj,null).TrimAllStrings();
}
}
}
}
感谢landi的解决方案。我改变了他的方法,添加了对带有索引参数的类的支持,并在继续之前检查obj是否为空
public static void TrimAllStrings<TSelf>(this TSelf obj)
{
if (obj == null)
return;
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
foreach (PropertyInfo p in obj.GetType().GetProperties(flags))
{
Type currentNodeType = p.PropertyType;
if (currentNodeType == typeof(String))
{
string currentValue = (string)p.GetValue(obj, null);
if (currentValue != null)
{
p.SetValue(obj, currentValue.Trim(), null);
}
}
// see http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection
else if (currentNodeType != typeof(object) && Type.GetTypeCode(currentNodeType) == TypeCode.Object)
{
if (p.GetIndexParameters().Length == 0)
{
p.GetValue(obj, null).TrimAllStrings();
}else
{
p.GetValue(obj, new Object[] { 0 }).TrimAllStrings();
}
}
}
}
公共静态void TrimAllStrings(此TSelf obj)
{
if(obj==null)
返回;
BindingFlags flags=BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlatterHierarchy;
foreach(房地产)
public static void TrimAllStrings<TSelf>(this TSelf obj)
{
if (obj == null)
return;
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
foreach (PropertyInfo p in obj.GetType().GetProperties(flags))
{
Type currentNodeType = p.PropertyType;
if (currentNodeType == typeof(String))
{
string currentValue = (string)p.GetValue(obj, null);
if (currentValue != null)
{
p.SetValue(obj, currentValue.Trim(), null);
}
}
// see http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection
else if (currentNodeType != typeof(object) && Type.GetTypeCode(currentNodeType) == TypeCode.Object)
{
if (p.GetIndexParameters().Length == 0)
{
p.GetValue(obj, null).TrimAllStrings();
}else
{
p.GetValue(obj, new Object[] { 0 }).TrimAllStrings();
}
}
}
}
public static class ExtensionMethods
{
public static void TrimAllStrings<TSelf>(this TSelf obj)
{
if(obj != null)
{
if(obj is IEnumerable)
{
foreach(var listItem in obj as IEnumerable)
{
listItem.TrimAllStrings();
}
}
else
{
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
foreach (PropertyInfo p in obj.GetType().GetProperties(flags))
{
Type currentNodeType = p.PropertyType;
if (currentNodeType == typeof (String))
{
string currentValue = (string)p.GetValue(obj, null);
if (currentValue != null)
{
p.SetValue(obj, currentValue.Trim(), null);
}
}
// see http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection
else if (currentNodeType != typeof (object) && Type.GetTypeCode(currentNodeType) == TypeCode.Object)
{
p.GetValue(obj, null).TrimAllStrings();
}
}
}
}
}
}
public static class ExtensionMethods
{
public static void TrimAllStrings<TSelf>(this TSelf obj)
{
if(obj != null)
{
if(obj is IEnumerable)
{
foreach(var listItem in obj as IEnumerable)
{
listItem.TrimAllStrings();
}
}
else
{
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
foreach (PropertyInfo p in obj.GetType().GetProperties(flags))
{
Type currentNodeType = p.PropertyType;
if (currentNodeType == typeof (String))
{
string currentValue = (string)p.GetValue(obj, null);
if (currentValue != null && p.CanWrite)
{
p.SetValue(obj, currentValue.Trim(), null);
}
}
// see http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection
else if (currentNodeType != typeof (object) && Type.GetTypeCode(currentNodeType) == TypeCode.Object)
{
p.GetValue(obj, null).TrimAllStrings();
}
}
}
}
}
}