[英]Fastest way for Get Value of a property (Reflection) in C#
I want to know what is fastest way to get value (only for this problem) from an object`s property ? 我想知道从对象的属性中获取价值的最快方法(仅针对此问题)是什么?
after some searching I saw a post from @MarkGravell in this site 经过一番搜索,我在这个网站上看到了@MarkGravell的帖子
He wrote this code : 他写了这段代码:
using System;
using System.Reflection;
using System.Reflection.Emit;
public class Foo
{
public Foo(int bar)
{
Bar = bar;
}
private int Bar { get; set; }
}
static class Program {
static void Main()
{
var method = new DynamicMethod("cheat", typeof(int),
new[] { typeof(object) }, typeof(Foo), true);
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, typeof(Foo));
il.Emit(OpCodes.Callvirt, typeof(Foo).GetProperty("Bar",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
).GetGetMethod(true));
il.Emit(OpCodes.Ret);
var func = (Func<object, int>)method.CreateDelegate(
typeof(Func<object, int>));
var obj = new Foo(123);
Console.WriteLine(func(obj));
}
}
OR 要么
var method = typeof(Foo).GetProperty("Bar",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.GetGetMethod(true);
var func = (Func<Foo, int>)
Delegate.CreateDelegate(typeof(Func<Foo, int>), method);
I changed it to 我改成了
var pt = propertyInfo.PropertyType; // I dont know what is Type
var method = pt.GetProperty("Bar",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.GetGetMethod(true);
var func = (Func<Foo, object>) // I dont know what is return type so set object !!!
Delegate.CreateDelegate(typeof(Func<Foo, object>), method); // I want get value as object ?!!!
return func(entity).ToString(); // cast return value to string
but I got an exception 但我得到了一个例外
Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
I dont know what is my property type It can be anything How customize code for this purpose ? 我不知道我的属性类型是什么它可以是任何东西如何为此目的定制代码?
If anyone can help me in better way (fastest way) without property Type restriction please introduce it 如果有人能以更好的方式(最快的方式)帮助我没有财产类型限制请介绍它
The Delegate.CreateDelegate
will not work in this case, because you have to cast the resulting delegate to some known type, otherwise all you have is DynamicInvoke
which is not better than direct invocation of PropertyInfo
(see here explanation by Marc Gravell). 该Delegate.CreateDelegate
不会在这种情况下工作,因为你所得到的委托投给一些已知的类型,否则你只有DynamicInvoke
这是不是比直接调用更好PropertyInfo
(见这里由Marc Gravell解释)。
The most generic way I've seen which does not involve lambda expressions (like Sriram Sakthivel suggested) is shown by Jon Skeet here . Jon Skeet 在这里展示了我所见过的最通用的方法,它不涉及lambda表达式(如Sriram Sakthivel建议)。 Building on his approach and the fact we can get the actual property return type from PropertyInfo
, we can invent something custom-tailored for properties invocation. 基于他的方法以及我们可以从PropertyInfo
获取实际属性返回类型的事实,我们可以发明为属性调用定制的东西。
First, we define an interface: 首先,我们定义一个接口:
public interface IPropertyCallAdapter<TThis>
{
object InvokeGet(TThis @this);
//add void InvokeSet(TThis @this, object value) if necessary
}
Then, an implementation of the interface: 然后,接口的实现:
public class PropertyCallAdapter<TThis, TResult> : IPropertyCallAdapter<TThis>
{
private readonly Func<TThis, TResult> _getterInvocation;
public PropertyCallAdapter(Func<TThis, TResult> getterInvocation)
{
_getterInvocation = getterInvocation;
}
public object InvokeGet(TThis @this)
{
return _getterInvocation.Invoke(@this);
}
}
The InvokeGet
method looks mostly like the one Jon Skeet uses. InvokeGet
方法看起来与Jon Skeet使用的方法类似。
Now, to the "magic" part. 现在,到了“魔术”部分。 We define a service which will build and cache an instance of the provider. 我们定义了一个服务,它将构建和缓存提供者的实例。 It looks like this: 它看起来像这样:
public class PropertyCallAdapterProvider<TThis>
{
private static readonly Dictionary<string, IPropertyCallAdapter<TThis>> _instances =
new Dictionary<string,IPropertyCallAdapter<TThis>>();
public static IPropertyCallAdapter<TThis> GetInstance(string forPropertyName)
{
IPropertyCallAdapter<TThis> instance;
if (!_instances.TryGetValue(forPropertyName, out instance))
{
var property = typeof(TThis).GetProperty(
forPropertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo getMethod;
Delegate getterInvocation = null;
if (property != null && (getMethod = property.GetGetMethod(true)) != null)
{
var openGetterType = typeof(Func<,>);
var concreteGetterType = openGetterType
.MakeGenericType(typeof(TThis), property.PropertyType);
getterInvocation =
Delegate.CreateDelegate(concreteGetterType, null, getMethod);
}
else
{
//throw exception or create a default getterInvocation returning null
}
var openAdapterType = typeof(PropertyCallAdapter<,>);
var concreteAdapterType = openAdapterType
.MakeGenericType(typeof(TThis), property.PropertyType);
instance = Activator
.CreateInstance(concreteAdapterType, getterInvocation)
as IPropertyCallAdapter<TThis>;
_instances.Add(forPropertyName, instance);
}
return instance;
}
}
Here, without knowing at compile time the exact TResult
type, we create the adapter and cache it for subsequent usage in order to prevent heavy reflection calls in the future. 这里,在不知道编译时确切的TResult
类型的情况下,我们创建适配器并将其缓存以供后续使用,以防止将来进行大量反射调用。
That's it. 而已。 You can use it in the following way: 您可以通过以下方式使用它:
PropertyCallAdapterProvider<Foo>.GetInstance("Bar").InvokeGet(fooInstance)
Also, you can easily extend this for property setters if necessary. 此外,如有必要,您可以轻松地为属性设置者扩展它。
On my machine those are the results for accessing the getter in loop ten million times, using various methods, when the adapter instance is pre-fetched from the provider before entering the loop: 在我的机器上,当在进入循环之前从提供程序预取适配器实例时,这些是使用各种方法在循环中访问getter一千万次的结果:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.