首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

改善篇《不使用反射进行C#属性的运行时动态访问》

2012-07-24 
改进篇《不使用反射进行C#属性的运行时动态访问》?在工作中看到不使用反射进行C#属性的运行时动态访问:http:

改进篇《不使用反射进行C#属性的运行时动态访问》

?在工作中看到

不使用反射进行C#属性的运行时动态访问:http://www.cnblogs.com/nankezhishi/archive/2012/02/11/dynamicaccess.html这篇文章后觉得很不错!但是在运用其代码的过程中也发现了这个代码存在的一些bug,经过努力,已经把它fix掉了,现在分享我修改后的代码:Dictionary只放存在的类和属性的 GET、SET委托:<key???????? ,??Value><类+属性名,??对应的GET、SET委托>如果类名或者属性名不存在,则不会给添加到这个单列的Dictionary中。
1.修改了在PropertyAccessor构造时抛出找不到GET SET Method的异常。此异常的原因是因为有些property没有public Get 或者Set方法,导致propertyInfo.GetGetMethod()/GetSetMethod() 时返回null,继而导致Delegate?.CreateDelegate创建失败。 2.增加了一个抛异常的辅助类,增强了异常处理机制。3.将MemberAccessor 设计成为单列模式,增加性能,方便调用。4.经过测试,没有引入其他bug。
using System;using System.Collections.Generic;using System.Reflection;namespace XXX.Common{    internal interface INamedMemberAccessor    {        object GetValue(object instance);        void SetValue(object instance, object newValue);    }    /// <summary>    /// Abstraction of the function of accessing member of a object at runtime.    /// </summary>    public interface IMemberAccessor    {        /// <summary>        /// Get the member value of an object.        /// </summary>        /// <param name="instance">The object to get the member value from.</param>        /// <param name="memberName">The member name, could be the name of a property of field. Must be public member.</param>        /// <returns>The member value</returns>        object GetValue(object instance, string memberName);        /// <summary>        /// Set the member value of an object.        /// </summary>        /// <param name="instance">The object to get the member value from.</param>        /// <param name="memberName">The member name, could be the name of a property of field. Must be public member.</param>        /// <param name="newValue">The new value of the property for the object instance.</param>        void SetValue(object instance, string memberName, object newValue);    }    internal class PropertyAccessor<T, P> : INamedMemberAccessor    {        private Func<T, P> m_GetValueDelegate;        private Action<T, P> m_SetValueDelegate;        public PropertyAccessor(PropertyInfo propertyInfo)        {            Guard.ArgumentNotNull(propertyInfo, "Property can't be null");            var getMethodInfo = propertyInfo.GetGetMethod();            if (null != getMethodInfo)            {                m_GetValueDelegate = (Func<T, P>)Delegate.CreateDelegate(typeof(Func<T, P>), getMethodInfo);            }            var setMethodInfo = propertyInfo.GetSetMethod();            if (null != setMethodInfo)            {                m_SetValueDelegate = (Action<T, P>)Delegate.CreateDelegate(typeof(Action<T, P>), setMethodInfo);            }        }        public object GetValue(object instance)        {            Guard.ArgumentNotNull(m_GetValueDelegate, "The Property doesn't have GetMethod");            return m_GetValueDelegate((T)instance);        }        public void SetValue(object instance, object newValue)        {            Guard.ArgumentNotNull(m_SetValueDelegate, "The Property doesn't have SetMethod");            m_SetValueDelegate((T)instance, (P)newValue);        }    }    /// <summary>    /// Singleton, MemberAccessor used to accessing member of a object at runtime.    /// </summary>    public class MemberAccessor : IMemberAccessor    {        #region Singleton        private MemberAccessor() { }        public static MemberAccessor Instance        {            get { return Nested.m_instance; }        }        private class Nested        {            static Nested() { }            internal static readonly MemberAccessor m_instance = new MemberAccessor();        }        #endregion        private static Dictionary<string, INamedMemberAccessor> m_accessorCache = new Dictionary<string, INamedMemberAccessor>();        /// <summary>        /// Get the member value of an object.        /// </summary>        /// <param name="instance">The object to get the member value from.</param>        /// <param name="memberName">The member name, could be the name of a property of field. Must be public member.</param>        /// <returns>The member value</returns>        public object GetValue(object instance, string memberName)        {            INamedMemberAccessor ma = FindAccessor(instance, memberName);            Guard.ArgumentNotNull(ma, "The instance doesn't have this property");            return ma.GetValue(instance);        }        /// <summary>        /// Set the member value of an object.        /// </summary>        /// <param name="instance">The object to get the member value from.</param>        /// <param name="memberName">The member name, could be the name of a property of field. Must be public member.</param>        /// <param name="newValue">The new value of the property for the object instance.</param>        public void SetValue(object instance, string memberName, object newValue)        {            INamedMemberAccessor ma = FindAccessor(instance, memberName);            Guard.ArgumentNotNull(ma, "The instance doesn't have this property");            ma.SetValue(instance, newValue);        }        private INamedMemberAccessor FindAccessor(object instance, string memberName)        {            Type type = instance.GetType();            string key = type.FullName + memberName;            INamedMemberAccessor accessor = null;            if (!m_accessorCache.TryGetValue(key, out accessor))            {                #region bug fix from Ambiguous Match Exception                PropertyInfo propInfo = type.GetProperty(memberName, BindingFlags.DeclaredOnly |                                    BindingFlags.Public | BindingFlags.NonPublic |                                    BindingFlags.Instance);                if (null == propInfo)                {                    propInfo = type.GetProperty(memberName);                }                #endregion                if (null == propInfo)                {                    return null;                }                else                {                    accessor = Activator.CreateInstance(typeof(PropertyAccessor<,>).MakeGenericType(type, propInfo.PropertyType), propInfo) as INamedMemberAccessor;                    m_accessorCache.Add(key, accessor);                }            }            return accessor;        }    }}
???
using System;namespace XXX.Common{    /// <summary>    /// Common guard clauses    /// </summary>    public static class Guard    {        /// <summary>        /// Checks an argument to ensure it isn't null        /// </summary>        /// <param name="argumentValue">The argument value to check.</param>        /// <param name="argumentName">The name of the argument.</param>        public static void ArgumentNotNull(object argumentValue, string argumentName)        {            if (argumentValue == null)            {                throw new ArgumentNullException(argumentName);            }        }    }}

?

热点排行