c# – CreateDelegate而不是SetValue的Reflection
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – CreateDelegate而不是SetValue的Reflection,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5477字,纯文字阅读大概需要8分钟。
内容图文
![c# – CreateDelegate而不是SetValue的Reflection](/upload/InfoBanner/zyjiaocheng/816/073e8029fdbe4452b8e8cf83a94fac43.jpg)
我尝试在blog post上发布了Jon Skeet的this question解决方案,用一个使用委托的非反射方法替换SetValue方法.
与blog post中的解决方案的不同之处在于SetValue是无效的,并且我得到了类型’System.Void’可能不会被用作类型参数. MethodInfo中的异常miConstructedHelper = miGenericHelper.MakeGenericMethod(typeof(G),pMethod.GetParameters()[0] .ParameterType,pMethod.ReturnType);.
这是我对MagicMethod的实现:
public class Instantiator<T> where T : new()
{
private T instance;
private IDictionary<string, PropertyInfo> properties;
private Func<PropertyInfo, object, object> _fncSetValue;
public Instantiator()
{
Type type = typeof(T);
properties = type.GetProperties().GroupBy(p => p.Name).ToDictionary(g => g.Key, g => g.ToList().First());
MethodInfo miSetValue = typeof(PropertyInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object), typeof(object[]) });
_fncSetValue = SetValueMethod<PropertyInfo>(miSetValue);
}
public void CreateNewInstance()
{
instance = new T();
}
public void SetValue(string pPropertyName, object pValue)
{
if (pPropertyName == null) return;
PropertyInfo property;
if (!properties.TryGetValue(pPropertyName, out property)) return;
TypeConverter tc = TypeDescriptor.GetConverter(property.PropertyType);
//substitute this line
//property.SetValue(instance, tc.ConvertTo(pValue, property.PropertyType), null);
//with this line
_fncSetValue(property, new object[] { instance, tc.ConvertTo(pValue, property.PropertyType), null });
}
public T GetInstance()
{
return instance;
}
private static Func<G, object, object> SetValueMethod<G>(MethodInfo pMethod) where G : class
{
MethodInfo miGenericHelper = typeof(Instantiator<T>).GetMethod("SetValueMethodHelper", BindingFlags.Static | BindingFlags.NonPublic);
MethodInfo miConstructedHelper = miGenericHelper.MakeGenericMethod(typeof(G), pMethod.GetParameters()[0].ParameterType, pMethod.ReturnType);
object retVal = miConstructedHelper.Invoke(null, new object[] { pMethod });
return (Func<G, object, object>) retVal;
}
private static Func<TTarget, object, object> SetValueMethodHelper<TTarget, TParam, TReturn>(MethodInfo pMethod) where TTarget : class
{
Func<TTarget, TParam, TReturn> func = (Func<TTarget, TParam, TReturn>)Delegate.CreateDelegate(typeof(Func<TTarget, TParam, TReturn>), pMethod);
Func<TTarget, object, object> retVal = (TTarget target, object param) => func(target, (TParam) param);
return retVal;
}
}
解决方法:
您在代码中使用Func. Func用于具有返回类型的方法.对于返回void的方法,您需要使用Action.
您的代码需要如下所示:
public class Instantiator<T> where T : new()
{
private T instance;
private IDictionary<string, PropertyInfo> properties;
private Action<PropertyInfo, object, object, object> _fncSetValue;
public Instantiator()
{
Type type = typeof(T);
properties = type.GetProperties()
.GroupBy(p => p.Name)
.ToDictionary(g => g.Key, g => g.ToList().First());
var types = new Type[] { typeof(object), typeof(object),
typeof(object[]) };
var miSetValue = typeof(PropertyInfo).GetMethod("SetValue", types);
_fncSetValue = SetValueMethod<PropertyInfo>(miSetValue);
}
public void CreateNewInstance()
{
instance = new T();
}
public void SetValue(string pPropertyName, object pValue)
{
if (pPropertyName == null) return;
PropertyInfo property;
if (!properties.TryGetValue(pPropertyName, out property)) return;
TypeConverter tc = TypeDescriptor.GetConverter(property.PropertyType);
var value = tc.ConvertTo(pValue, property.PropertyType);
_fncSetValue(property, instance, value, null);
}
public T GetInstance()
{
return instance;
}
private static Action<G, object, object, object> SetValueMethod<G>(MethodInfo pMethod) where G : class
{
var miGenericHelper =
typeof(Instantiator<T>).GetMethod("SetValueMethodHelper",
BindingFlags.Static |
BindingFlags.NonPublic);
var parameters = pMethod.GetParameters();
var miConstructedHelper = miGenericHelper.MakeGenericMethod(typeof(G),
parameters[0].ParameterType,
parameters[1].ParameterType,
parameters[2].ParameterType);
var retVal = miConstructedHelper.Invoke(null, new object[] { pMethod });
return (Action<G, object, object, object>) retVal;
}
private static Action<TTarget, object, object, object> SetValueMethodHelper<TTarget, TParam1, TParam2, TParam3>(MethodInfo pMethod) where TTarget : class
{
var func = (Action<TTarget, TParam1, TParam2, TParam3>)Delegate.CreateDelegate(typeof(Action<TTarget, TParam1, TParam2, TParam3>), pMethod);
Action<TTarget, object, object, object> retVal =
(target, param1, param2, param3) =>
func(target, (TParam1) param1, (TParam2) param2, (TParam3) param3);
return retVal;
}
}
由于您不想调用像Jon Skeet这样的任意方法,因此您可以大大简化代码.您的代码中不需要调用MethodInfo.Invoke,因此不需要委托.您可以直接在返回的PropertyInfo上调用SetValue.没有必要使用代理人的绕行,而代理人又完全调用该方法.此外,类型转换不是必需的,因为SetValue无论如何都需要一个对象.
您的代码可以像这样简单:
public class SimpleInstantiator<T> where T : new()
{
private T instance;
private IDictionary<string, PropertyInfo> properties;
public SimpleInstantiator()
{
Type type = typeof(T);
properties = type.GetProperties()
.GroupBy(p => p.Name)
.ToDictionary(g => g.Key, g => g.ToList().First());
}
public void CreateNewInstance()
{
instance = new T();
}
public void SetValue(string pPropertyName, object pValue)
{
if (pPropertyName == null) return;
PropertyInfo property;
if (!properties.TryGetValue(pPropertyName, out property)) return;
property.SetValue(instance, pValue, null);
}
public T GetInstance()
{
return instance;
}
}
性能测试表明,该版本仅占前一版本的50%左右.
性能略有提高是因为我们在调用链中避免了两个不必要的委托.但是,绝大多数的速度提升都是因为我们删除了类型转换.
内容总结
以上是互联网集市为您收集整理的c# – CreateDelegate而不是SetValue的Reflection全部内容,希望文章能够帮你解决c# – CreateDelegate而不是SetValue的Reflection所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。