C# 修剪所有字符串属性

C# 修剪所有字符串属性,c#,reflection,C#,Reflection,我需要修剪对象中的一些字符串属性,但我不想转到所有对象和属性,在设置属性中执行修剪方法(有很多对象、300+和很多字符串属性) 提示:我的所有对象都有一个名为CoreTransaction的超类,因此我可以使用它(通过某种反射)更轻松地完成这项工作 这可能吗?您可以使用反射来执行以下操作: var stringProperties = obj.GetType().GetProperties() .Where(p => p.Property

我需要修剪对象中的一些字符串属性,但我不想转到所有对象和属性,在设置属性中执行修剪方法(有很多对象、300+和很多字符串属性)

提示:我的所有对象都有一个名为CoreTransaction的超类,因此我可以使用它(通过某种反射)更轻松地完成这项工作


这可能吗?

您可以使用反射来执行以下操作:

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();
                    }
                }
            }
        }
    }
}