Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Delegate.DynamicVoke太慢,如何将调用更改为调用?_C#_.net 3.5_Dynamic_Delegates_Invoke - Fatal编程技术网

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)。这里的问题是,不仅属性的名称在运行时不同,而且类型也不同。这迫使你使用