C# Delegate.DynamicVoke太慢,如何将调用更改为调用?
我已经读过,我应该创建并重用委托来获取对象属性的值 我使用此代码创建委托C# Delegate.DynamicVoke太慢,如何将调用更改为调用?,c#,.net-3.5,dynamic,delegates,invoke,C#,.net 3.5,Dynamic,Delegates,Invoke,我已经读过,我应该创建并重用委托来获取对象属性的值 我使用此代码创建委托 var objParm = Expression.Parameter(property.DeclaringType, "o"); Type delegateType = typeof(Func<,>).MakeGenericType(property.DeclaringType, property.PropertyType); var lambda = Expression.Lamb
var objParm = Expression.Parameter(property.DeclaringType, "o");
Type delegateType = typeof(Func<,>).MakeGenericType(property.DeclaringType, property.PropertyType);
var lambda = Expression.Lambda(delegateType, Expression.Property(objParm, property.Name), objParm);
return lambda.Compile()
但是打了电话之后,我得到了一个例外
MethodInfo must be a RuntimeMethodInfo.
每个属性都有一个缓存类,可以在其中存储动态创建的委托
我应该怎么做才能使用“正常”调用
非常感谢。您必须发出一个
Func
委托,并根据需要在lambda内部和检索结果时强制转换。如果您在编译时不知道委托的类型,则不能直接调用它,因为您不知道它采用什么类型的参数,也不知道返回类型
另外,请注意,您可能只是围绕
属性.getMethod()
创建了一个委托——这里没有理由编译您自己的方法。只需使用属性getter方法。您必须发出一个Func
委托,并根据需要在lambda内部和检索结果时强制转换。如果您在编译时不知道委托的类型,则不能直接调用它,因为您不知道它采用什么类型的参数,也不知道返回类型
另外,请注意,您可能只是围绕
属性.getMethod()
创建了一个委托——这里没有理由编译您自己的方法。只需使用属性getter方法。我创建了一个类,当我需要使用属性名称作为文本来访问属性时,可以使用该类。该类缓存一个类的所有属性
用法:
PropertyWrapper<User> wrapper = new PropertyWrapper<User>();
wrapper.SetValue("FirstName", "arne");
int age = (int)wrapper.GetValue("Age");
PropertyRapper包装器=新的PropertyRapper();
wrapper.SetValue(“FirstName”、“arne”);
int age=(int)wrapper.GetValue(“age”);
班级
public class PropertyWrapper<T>
{
private Dictionary<string, Methods> _properties = new Dictionary<string, Methods>();
private class Methods
{
public MethodBase Get { get; set; }
public MethodBase Set { get; set; }
}
public PropertyWrapper()
{
foreach (var item in typeof(T).GetProperties())
{
if (!item.CanRead && !item.CanWrite)
continue;
var mappings = new Methods();
if (item.CanRead)
mappings.Get = item.GetGetMethod();
if (item.CanWrite)
mappings.Set = item.GetSetMethod();
_properties.Add(item.Name, mappings);
}
}
public object GetValue(T instance, string name)
{
Methods mappings;
if (_properties.TryGetValue(name, out mappings) && mappings.Get != null)
return mappings.Get.Invoke(instance, null);
throw new MappingException("Specified property cannot be read", typeof(T), name);
}
public void SetValue(T instance, string name, object value)
{
Methods mappings;
if (_properties.TryGetValue(name, out mappings) && mappings.Set != null)
{
mappings.Set.Invoke(instance, new[] { value });
return;
}
throw new MappingException("Specified property cannot be written.", typeof(T), name);
}
}
public class MappingException : Exception
{
public MappingException(string errMsg, Type type, string propertyName)
: base(errMsg)
{
ReflectedType = type;
PropertyName = propertyName;
}
public Type ReflectedType { get; private set; }
public string PropertyName { get; private set; }
}
公共类PropertyRapper
{
私有字典_properties=新字典();
私有类方法
{
公共MethodBase Get{Get;set;}
公共MethodBase集合{get;Set;}
}
公共财产说唱人()
{
foreach(typeof(T).GetProperties()中的变量项)
{
如果(!item.CanRead&&!item.CanWrite)
继续;
var映射=新方法();
如果(项目.可读取)
mappings.Get=item.getMethod();
if(item.CanWrite)
mappings.Set=item.GetSetMethod();
_添加(item.Name,映射);
}
}
公共对象GetValue(T实例,字符串名称)
{
方法映射;
if(_properties.TryGetValue(name,out映射)&&mappings.Get!=null)
返回mappings.Get.Invoke(实例,null);
抛出新的MappingException(“无法读取指定的属性”,typeof(T),name);
}
public void SetValue(T实例、字符串名称、对象值)
{
方法映射;
if(_properties.TryGetValue(name,out mappings)&&mappings.Set!=null)
{
Invoke(实例,new[]{value});
返回;
}
抛出新的MappingException(“无法写入指定的属性。”,typeof(T),name);
}
}
公共类映射异常:异常
{
公共映射异常(字符串errMsg、类型Type、字符串propertyName)
:base(errMsg)
{
反射类型=类型;
PropertyName=PropertyName;
}
公共类型反射类型{get;private set;}
公共字符串PropertyName{get;private set;}
}
我创建了一个类,当我需要使用属性名称作为文本来访问属性时,可以使用该类。该类缓存一个类的所有属性
用法:
PropertyWrapper<User> wrapper = new PropertyWrapper<User>();
wrapper.SetValue("FirstName", "arne");
int age = (int)wrapper.GetValue("Age");
PropertyRapper包装器=新的PropertyRapper();
wrapper.SetValue(“FirstName”、“arne”);
int age=(int)wrapper.GetValue(“age”);
班级
public class PropertyWrapper<T>
{
private Dictionary<string, Methods> _properties = new Dictionary<string, Methods>();
private class Methods
{
public MethodBase Get { get; set; }
public MethodBase Set { get; set; }
}
public PropertyWrapper()
{
foreach (var item in typeof(T).GetProperties())
{
if (!item.CanRead && !item.CanWrite)
continue;
var mappings = new Methods();
if (item.CanRead)
mappings.Get = item.GetGetMethod();
if (item.CanWrite)
mappings.Set = item.GetSetMethod();
_properties.Add(item.Name, mappings);
}
}
public object GetValue(T instance, string name)
{
Methods mappings;
if (_properties.TryGetValue(name, out mappings) && mappings.Get != null)
return mappings.Get.Invoke(instance, null);
throw new MappingException("Specified property cannot be read", typeof(T), name);
}
public void SetValue(T instance, string name, object value)
{
Methods mappings;
if (_properties.TryGetValue(name, out mappings) && mappings.Set != null)
{
mappings.Set.Invoke(instance, new[] { value });
return;
}
throw new MappingException("Specified property cannot be written.", typeof(T), name);
}
}
public class MappingException : Exception
{
public MappingException(string errMsg, Type type, string propertyName)
: base(errMsg)
{
ReflectedType = type;
PropertyName = propertyName;
}
public Type ReflectedType { get; private set; }
public string PropertyName { get; private set; }
}
公共类PropertyRapper
{
私有字典_properties=新字典();
私有类方法
{
公共MethodBase Get{Get;set;}
公共MethodBase集合{get;Set;}
}
公共财产说唱人()
{
foreach(typeof(T).GetProperties()中的变量项)
{
如果(!item.CanRead&&!item.CanWrite)
继续;
var映射=新方法();
如果(项目.可读取)
mappings.Get=item.getMethod();
if(item.CanWrite)
mappings.Set=item.GetSetMethod();
_添加(item.Name,映射);
}
}
公共对象GetValue(T实例,字符串名称)
{
方法映射;
if(_properties.TryGetValue(name,out映射)&&mappings.Get!=null)
返回mappings.Get.Invoke(实例,null);
抛出新的MappingException(“无法读取指定的属性”,typeof(T),name);
}
public void SetValue(T实例、字符串名称、对象值)
{
方法映射;
if(_properties.TryGetValue(name,out mappings)&&mappings.Set!=null)
{
Invoke(实例,new[]{value});
返回;
}
抛出新的MappingException(“无法写入指定的属性。”,typeof(T),name);
}
}
公共类映射异常:异常
{
公共映射异常(字符串errMsg、类型Type、字符串propertyName)
:base(errMsg)
{
反射类型=类型;
PropertyName=PropertyName;
}
公共类型反射类型{get;private set;}
公共字符串PropertyName{get;private set;}
}
“我已经读到,我应该创建并重用委托来获取对象属性的值。”在极少数情况下,这是正确的,“非常”是这里的关键词。大多数时候,你应该只是你的x.Property
。是的,你完全正确,这是我在解释中的错误。与反射一致(GetValue,SetValue)。这里的问题是,不仅属性的名称在运行时不同,而且类型也不同。这迫使你使用