在工作中看到
这篇文章后觉得很不错!但是在运用其代码的过程中也发现了这个代码存在的一些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);
}
}
}
}
分享到:
相关推荐
NULL 博文链接:https://totoxian.iteye.com/blog/1404096
最近一段时间学习使用C#编程,因为用惯了Delphi,发现C#类库还是不太完善(我 用的是.Net Framework 1.0,不知道.Net Framework 1.1有哪些改进),此外 Visual Studio 2002也有不完善的地方,不知道Visual ...
C#,利用反射动态创建对象 C#,利用反射动态创建对象 C#,利用反射动态创建对象 C#,利用反射动态创建对象
c#winfrom PropertyGrid 运行时变更属性项 关于PropertyGrid相关参见:http://www.cnblogs.com/mywebname/archive/2007/11/15/959732.html
C#net反射实现访问类中的私有变量或者方法
1.不使用反射机制就可以动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型 2.应用程序需要在运行时从某个特定的程序集中载入一个特定的类型,以便实现某个任务时可以用到该技术。 3.主要应用与...
C# 反射,操作权限(新增,删除等),动态实例化类,一个C/S系统,每个模块上面都有很多操作按钮,你不可能每一窗体内在设权限的时候都用btn.enable=false/true,这样太烦了,可以作一个控件,这样统一按钮名称,然后...
利用Type动态创建类实例(C#反射)可以演变抽象工厂
使用C++模拟C#中的“反射”的动态创建功能,实现对象的动态加载.在自定义类中使用DECLARE_REFLECTION声明反射;使用IMPLEMENT_REFLECTION实现反射。 程序运行过程可以使用Assembly::CreateInstance动态创建对象(可以...
C# 反射工厂示例C# 反射工厂示例C# 反射工厂示例C# 反射工厂示例C# 反射工厂示例C# 反射工厂示例C# 反射工厂示例C# 反射工厂示例C# 反射工厂示例C# 反射工厂示例
C# 利用反射动态创建对象,可以动态加载主菜单,可以根据主菜单来弹出窗体
反射(Reflection)是.NET中的重要机制,通过放射,可以在运行时获得.NET中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员的名称、限定符和参数...
C#dll的调用 dll源代码 动态链接库 dll动态链接 C#动态链接库
实用结合C#反射实现动态定时器定时任务工具,可结合XML配置文档,实现独立动态的定时配置;用于定时任务执行、消息推送、WebService任务等;附件为程序源码。工具历经多项目验证,不足之处;欢迎交流指正!
输入字符串如:Label,Button,TextBox等,根据反射原理,动态创建相应的控件,并且动态的控件可在右边的区域内拖动。
反射(Reflection)是.NET中的重要机制,通过放射,可以在运行时获得.NET中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员的名称、限定符和...
C#泛型、反射实例,分层,自动生成sql语句
可以使用C#的反射技术进行动态加载外部C#自己所写的Dll。进行项目整合。实现动态调用。该列子如果有什么问题可以留言
C# 通过反射调用com组件,封装了几个简单的方法方便使用反射调用com。 var obj=new ComObj("excel.application"); obj["Visible"]=true; obj. InvokeMethod("Application.Workbooks.Open", fileName);
c# 简单的IOC实现框架,包含通过配置,利用c#反射机制来动态注入