1. <i id='UewDc'><tr id='UewDc'><dt id='UewDc'><q id='UewDc'><span id='UewDc'><b id='UewDc'><form id='UewDc'><ins id='UewDc'></ins><ul id='UewDc'></ul><sub id='UewDc'></sub></form><legend id='UewDc'></legend><bdo id='UewDc'><pre id='UewDc'><center id='UewDc'></center></pre></bdo></b><th id='UewDc'></th></span></q></dt></tr></i><div id='UewDc'><tfoot id='UewDc'></tfoot><dl id='UewDc'><fieldset id='UewDc'></fieldset></dl></div>
      <tfoot id='UewDc'></tfoot>

        <small id='UewDc'></small><noframes id='UewDc'>

        • <bdo id='UewDc'></bdo><ul id='UewDc'></ul>

      1. <legend id='UewDc'><style id='UewDc'><dir id='UewDc'><q id='UewDc'></q></dir></style></legend>

        为属性设置器或获取器创建高性能开放委托

        Creating an performant open delegate for an property setter or getter(为属性设置器或获取器创建高性能开放委托)
        <legend id='MreyZ'><style id='MreyZ'><dir id='MreyZ'><q id='MreyZ'></q></dir></style></legend>
        • <tfoot id='MreyZ'></tfoot>

                <tbody id='MreyZ'></tbody>
            1. <small id='MreyZ'></small><noframes id='MreyZ'>

                <i id='MreyZ'><tr id='MreyZ'><dt id='MreyZ'><q id='MreyZ'><span id='MreyZ'><b id='MreyZ'><form id='MreyZ'><ins id='MreyZ'></ins><ul id='MreyZ'></ul><sub id='MreyZ'></sub></form><legend id='MreyZ'></legend><bdo id='MreyZ'><pre id='MreyZ'><center id='MreyZ'></center></pre></bdo></b><th id='MreyZ'></th></span></q></dt></tr></i><div id='MreyZ'><tfoot id='MreyZ'></tfoot><dl id='MreyZ'><fieldset id='MreyZ'></fieldset></dl></div>

                • <bdo id='MreyZ'></bdo><ul id='MreyZ'></ul>

                  本文介绍了为属性设置器或获取器创建高性能开放委托的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  开放委托是对没有目标的实例方法的委托.要调用它,您需要提供目标作为其第一个参数.它们是一种优化代码的聪明方法,否则会使用反射并且性能很差.有关公开代表的介绍,请参阅 this.您在实践中使用它的方式是使用昂贵的反射代码来构建这些开放的委托,但是您可以通过简单的委托调用非常便宜地调用它们.

                  An open delegate is a delegate to an instance method without the target. To call it you supply the target as its first parameter. They are a clever way to optimize code that otherwise would use reflection and have poor performance. For an intro to open delegates see this. The way you would use it in practice is to have expensive reflection code to build these open delegates, but then you would be able to call them very cheaply as a simple Delegate call.

                  我正在尝试编写将任意 PropertyInfo 转换为它的 setter 的委托的代码.到目前为止,我想出了这个:

                  I'm trying to write code that will transform an arbitrary PropertyInfo, into such an delegate for its setter. So far I came up with this:

                  using System;
                  using System.Collections.Generic;
                  using System.Linq;
                  using System.Text;
                  using System.Reflection;
                  
                  namespace Test
                  {
                      class TestClass
                      {
                          static Action<T, object> MakeSetterDelegate<T>(PropertyInfo property)
                          {
                              MethodInfo setMethod = property.GetSetMethod();
                              if (setMethod != null && setMethod.GetParameters().Length == 1) //skips over nasty index properties
                              {
                                  //To be able to bind to the delegate we have to create a delegate 
                                  //type like: Action<T,actualType> rather than Action<T,object>.
                                  //We use reflection to do that
                                  Type setterGenericType = typeof(Action<,>);
                                  Type delegateType = setterGenericType.MakeGenericType(new Type[] { typeof(T), property.PropertyType });
                                  var untypedDelegate = Delegate.CreateDelegate(delegateType, setMethod);
                  
                                  //we wrap the Action<T,actualType> delegate into an Action<T,object>
                                  Action<T, object> setter = (instance, value) =>
                                  {
                                      untypedDelegate.DynamicInvoke(new object[] { instance, value });
                                  };
                                  return setter;
                              }
                              else
                              {
                                  return null;
                              }
                          }
                  
                          int TestProp 
                          {
                              set
                              {
                                  System.Diagnostics.Debug.WriteLine("Called set_TestProp");
                              }
                          }
                  
                          static void Test() 
                          {
                              PropertyInfo property = typeof(TestClass).GetProperty("TestProp");
                              Action<TestClass, object> setter = MakeSetterDelegate<TestClass>(property);
                              TestClass instance = new TestClass();
                              setter(instance, 5);
                          }
                      }
                  }
                  

                  将为 getter 编写类似的代码.它可以工作,但是 setter 委托使用 DynamicInvoke 将 Action<derivedType> 转换为 Action<object>,我怀疑这会占用很大一部分我追求的优化.所以问题是:

                  Similar code would be written for the getter. It works, but the setter delegate uses a DynamicInvoke to convert from an Action<derivedType> to Action<object>, which I suspect is eating a good part of the optimization I'm after. So the questions are:

                  1. DynamicInvoke 真的值得关注吗?
                  2. 周围有吗?

                  推荐答案

                  DynamicInvoke 不会成为高性能的 setter.对泛型内部类型的反射是您更好的选择,因为这将允许您使用 typed 委托.另一种选择是DynamicMethod,但是你需要担心一些IL细节.

                  DynamicInvoke will not make a performant setter. Reflection against a generic inner type is your better option here, as this will allow you to use typed delegates. Another option is DynamicMethod, but then you need to worry about a few IL details.

                  可能想查看 HyperDescriptor,它将 IL 工作包装到 PropertyDescriptor 实现中.另一种选择是 Expression API(如果您使用的是 .NET 3.5 或更高版本):

                  You might want to look at HyperDescriptor, which wraps up the IL work into a PropertyDescriptor implementation. Another option is the Expression API (if you are using .NET 3.5 or above):

                  static Action<T, object> MakeSetterDelegate<T>(PropertyInfo property)
                  {
                      MethodInfo setMethod = property.GetSetMethod();
                      if (setMethod != null && setMethod.GetParameters().Length == 1)
                      {
                          var target = Expression.Parameter(typeof(T));
                          var value = Expression.Parameter(typeof(object));
                          var body = Expression.Call(target, setMethod,
                              Expression.Convert(value, property.PropertyType));
                          return Expression.Lambda<Action<T, object>>(body, target, value)
                              .Compile();
                      }
                      else
                      {
                          return null;
                      }
                  }
                  

                  或者使用泛型类型:

                      abstract class Setter<T>
                      {
                          public abstract void Set(T obj, object value);
                      }
                      class Setter<TTarget, TValue> : Setter<TTarget>
                      {
                          private readonly Action<TTarget, TValue> del;
                          public Setter(MethodInfo method)
                          {
                              del = (Action<TTarget, TValue>)
                                  Delegate.CreateDelegate(typeof(Action<TTarget, TValue>), method);
                          }
                          public override void Set(TTarget obj, object value)
                          {
                              del(obj, (TValue)value);
                          }
                  
                      }
                      static Action<T, object> MakeSetterDelegate<T>(PropertyInfo property)
                      {
                          MethodInfo setMethod = property.GetSetMethod();
                          if (setMethod != null && setMethod.GetParameters().Length == 1)
                          {
                              Setter<T> untyped = (Setter<T>) Activator.CreateInstance(
                                  typeof(Setter<,>).MakeGenericType(typeof(T),
                                  property.PropertyType), setMethod);
                              return untyped.Set;
                          }
                          else
                          {
                              return null;
                          }
                      }
                  

                  这篇关于为属性设置器或获取器创建高性能开放委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                  相关文档推荐

                  Multicast delegate weird behavior in C#?(C# 中的多播委托奇怪行为?)
                  Parameter count mismatch with Invoke?(参数计数与调用不匹配?)
                  How to store delegates in a List(如何将代表存储在列表中)
                  How delegates work (in the background)?(代表如何工作(在后台)?)
                  C# Asynchronous call without EndInvoke?(没有 EndInvoke 的 C# 异步调用?)
                  Delegate.CreateDelegate() and generics: Error binding to target method(Delegate.CreateDelegate() 和泛型:错误绑定到目标方法)
                    <tbody id='Vud82'></tbody>

                  <tfoot id='Vud82'></tfoot>

                    • <small id='Vud82'></small><noframes id='Vud82'>

                      1. <legend id='Vud82'><style id='Vud82'><dir id='Vud82'><q id='Vud82'></q></dir></style></legend>
                        <i id='Vud82'><tr id='Vud82'><dt id='Vud82'><q id='Vud82'><span id='Vud82'><b id='Vud82'><form id='Vud82'><ins id='Vud82'></ins><ul id='Vud82'></ul><sub id='Vud82'></sub></form><legend id='Vud82'></legend><bdo id='Vud82'><pre id='Vud82'><center id='Vud82'></center></pre></bdo></b><th id='Vud82'></th></span></q></dt></tr></i><div id='Vud82'><tfoot id='Vud82'></tfoot><dl id='Vud82'><fieldset id='Vud82'></fieldset></dl></div>
                          <bdo id='Vud82'></bdo><ul id='Vud82'></ul>