修剪所有字符串属性

rpf*_*rpf 15 c# reflection

我需要在我的对象中修剪一些字符串属性,但我不想去所有对象和属性,并且在set属性中做Trim方法(有很多对象,300+和很多字符串属性) .

一个提示:我的所有对象都有一个名为CoreTransaction的超类,所以我可以使用它(带某种反射)来更轻松地完成这个任务.

那可能吗?

谢谢.

Bal*_*a R 37

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) ;
}
Run Code Online (Sandbox Code Playgroud)

  • 我不需要考虑这里的逻辑.我唯一要补充的是你可能想对`SetValue`行进行空检查,因为`currentValue.Trim()`会抛出`NullReferenceException` :-) (9认同)
  • 真的很酷.我把它作为对象扩展.除了在执行`SetValue`之前需要进行空检查之外,在最初获取属性时对lambda表达式进行`p.CanWrite`检查也是安全的 - 这样我们确保不会尝试设置值只读属性. (2认同)

小智 16

感谢Bala R解决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));

        foreach (var stringProperty in stringProperties)
        {
            string currentValue = (string)stringProperty.GetValue(input, null);
            if (currentValue != null)
                stringProperty.SetValue(input, currentValue.Trim(), null);
        }
        return input;
    }
Run Code Online (Sandbox Code Playgroud)


OwN*_*OwN 7

我修复了landi 的答案以容纳子可空对象并处理 IEnumerable 集合(循环遍历对象列表和修剪字符串属性)。我对他的回答进行了编辑,但由于未涉及主题而被拒绝,但那是一堆垃圾。希望这对某人有所帮助,因为landi 的回答不适用于我拥有的所有对象类型。现在确实如此。

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();
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Buh*_*ica 5

我不确定要更改访问者的行为。这听起来一点也不容易。将修剪添加到您的基类如何?

    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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

(另外,请注意检查您的字段是否可以读取和写入。)

 

编辑: 然后您可以将这样的内容添加到您的基类中,并一次性修剪所有这些内容。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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


lan*_*ndi 5

我编写了一个扩展方法,它还处理引用类的子类和字符串(如parent.Child.Name)

public static class ExtensionMethods
{
    public static void TrimAllStrings<TSelf>(this TSelf obj)
    {
        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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)