简体   繁体   中英

Improvements with reflection and generics

Following on from another question on Stack Overflow by a different user, I thought I would try the code and see if I could improve it.

I would like clarification on a number of things:

  1. I am assuming that getting property information via reflection is costly? Correct?
  2. With PropertyInfo.SetValue(Object, Object, Object[]) what is the last parameter for? Am I safe passing in null?
  3. Is there any other improvements that are obvious in my code?

The whole point is a learning exercise to see if I can create something like Dapper (which is very nice) but without the nasty looking (because i have no idea) IL emit stuff. With this is mind, I tried to implement some sort of caching with the assumtion that reflection is bad for perfomance.


The Code

    private T CreateItemFromRow<T>(SqlDataReader row, List<PropertyInfo> properties, Dictionary<String, Int32> schema) where T : new()
    {
        T item = new T();
        if (schema != null && properties != null && row != null)
        {
            foreach (var property in properties)
            {
                if (schema.ContainsKey(property.Name))
                {
                    // is this ok?
                    if (row[0].GetType() == property.PropertyType)
                    {
                        property.SetValue(item, row[schema[property.Name]], null);
                    }
                    else
                    {
                        property.SetValue(item, Convert.ChangeType(row[schema[property.Name]], property.PropertyType), null);
                    }
                }
            }
        }
        return item;
    }

The properties is passed in from this method:

    private List<PropertyInfo> GetPropertyInformation<T>()
    {
        List<PropertyInfo> properties;

        Type _T = typeof(T);
        if (!PropertyCache.ContainsKey(_T))
        {
            properties = _T.GetProperties().ToList();
            PropertyCache.Add(_T, properties);
        }
        else
        {
            properties = PropertyCache[_T];
        }
        return properties;
    }

And this is the declaration of PropertyCache

private static Dictionary<Type, List<PropertyInfo>> PropertyCache { get; set; }
  1. Getting property information via reflection is costly, but so is accessing the properties via reflection. You're not gaining nearly as much from this approach as you could gain by avoiding reflection altogether. Besides, unless you have determined that this code is a performance bottleneck, most optimization here will be premature anyway.
  2. With PropertyInfo.SetValue(Object, Object, Object[]), the last parameter has to do with Index properties (eg dict[0] actually accesses an index property, and would pass an array with the 0 in that third parameter).
  3. I'd suggest using a ConcurrentDictionary for your PropertyCache . It will help to both simplify your code and make it thread-safe.

Reflection isn't exactly integer addition when it comes to performance, no. But, does it matter in the case where you are using it?

The third argument to PropertyInfo.SetValue() is for setting property indexers. That is for properties that are array like. That'll be null in most cases.

I don't see anything obvious. But it does seem like the sort of thing that'll be turning up hidden little corner cases and so on for a long time. In other words, it seems like a fantastic learning exercise, which is what you wanted.

听起来好像您正在考虑编写AutoMapper ,它已经考虑了有关此问题的一些性能方面的考虑。

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