简体   繁体   中英

Get properties of property of a custom data type, with reflection c#

Short description: I need to sanitize some text before it is saved in the database. We have a project that contain all the models that are used in our MVC application. There's a Save(T record) method that saves the entity to the database. What I was asked to do is to sanitize every property of type string of the incoming object, before saving it to the database. However, there's a problem: How do I sanitize the properties of the property of a custom data type, from the incoming entity?

Long description: Let's say I have a class of type Address and a class of type Person that has a property of type Address:

    public class Address
    {
        public string StreetName { get; set; }
        public string City { get; set; }
        public int StreetNumber { get; set; }
    }

    public class Person
    {
        public string PersonName { get; set; }
        public Address HomeAddress { get; set; }
    }

Before I was using this generic method to retrieve the properties of type string:

        public static void SanitizeObject<TEntity>(TEntity record)
        {
            var props =
                record.GetType().GetProperties()
                    .Where(x => x.CanRead && x.CanWrite)
                    .Where(x => x.PropertyType == typeof (string));
            foreach (var property in props)
            {
                string value = Convert.ToString(record.GetPropertyValue(property.Name));
                if (!string.IsNullOrEmpty(value))
                {
                    value = Sanitize(value);
                    record.SetPropertyValue(property.Name, value);
                }
            }
        }

In that case I will sanitize only the Person.PersonName , however, I need to sanitize also the Address.StreetName and the Address.City

Is there a way to write this lambda expression to get the childrens' properties of type string also? How should I perform this to get all the properties of type string so i could sanitize them?

It seems like you need a recursive method.

Pseudo-code:

public void SanitizeObject(object some)
{
    // We get properties which are of reference types because we don't want to iterate value types (do you want to sanitize an integer...?)
    foreach (PropertyInfo property in some.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(prop => !prop.PropertyType.IsValueType)
    {
        if (property.PropertyType == typeof (string))
        {
        // Do stuff to sanitize the string
        }
        else
        {
            // Get properties declared in the concrete class (skip inherited members)
            var properties = property.DeclaringType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);

            // Does the property type has properties?
            if (properties != null && properties.Length > 0)
            {
                // This gets the custom object and starts a recursion to sanitize its string properties if the object have string properties, of course...
                SanitizeObject(property.GetValue(some));
            }
        }
    }
}

Note that I removed the generic parameter. I believe that, as you'll use reflection to get properties to sanitize, there's no advantage on using generics at all. And using this approach you'll be able to sanitize any objects instead of only supporting entity types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM