title: Fast Delegate Accessors without using DynamicInvoke()?
body: <p>I'm recently developing a SQLite ORM, and I came across some issues about dynamic things, (I'm coding against C# 3.5). One of them is about how to get quickly a property value. I tried many different ways and one of them is really fast (almost fast as a native and hard-coded access) but the thing is that you need to use the generics while I would like just to provide the types. If I only provide types I'm stuck with a delegate (where only the slow and desperate DynamicInvoke Method is available) or using MethodInfo.Invoke()...</p>
  
  <p>So I'm wondering is there any proper ways to get this Invoke() (instead of the DynamicInvoke) when I have a delegate. I though about casting the Delegate into a Func but it does not work.</p>
  
  <p>Any tricks?</p>
  
  <pre class="lang-C# prettyprint-override"><code>class Program
  {
      static void Main(String[] args)
      {
          DummyClass dummyInstance= new DummyClass();
          dummyInstance.DummyMember = "I'm a Dummy Value!";
  
          Type typeDummyClass = typeof(DummyClass);
  
          PropertyInfo propertyInfo = typeDummyClass.GetProperty("DummyMember");
          MethodInfo methodInfo = propertyInfo.GetGetMethod();
  
          ParameterExpression parameterExpression = Expression.Parameter(typeDummyClass, "Instance");
          Expression expression = Expression.Property(parameterExpression, propertyInfo.Name);
  
          Type funcType = typeof(Func&lt;,&gt;);
          Type funcGenericType = funcType.MakeGenericType(typeDummyClass, propertyInfo.PropertyType);
  
          LambdaExpression lambdaExpression = Expression.Lambda(funcGenericType, expression, parameterExpression);
          Expression&lt;Func&lt;DummyClass, String&gt;&gt; expressionTyped = Expression.Lambda&lt;Func&lt;DummyClass, String&gt;&gt;(expression, parameterExpression);
          Delegate @delegate = lambdaExpression.Compile();
          Func&lt;DummyClass, String&gt; func = expressionTyped.Compile();
  
          TimeSpan timeSpanNativeAccess = new TimeSpan(0);
          TimeSpan timeSpanGetValueCachedAccess = new TimeSpan(0);
          TimeSpan timeSpanMethodInfoCachedAccess = new TimeSpan(0);
          TimeSpan timeSpanDelegateCachedAccess = new TimeSpan(0);
          TimeSpan timeSpanFuncCachedAccess = new TimeSpan(0);
  
          for (UInt32 i = 0; i &lt; 100000; i++)
          {
              Stopwatch stopwatchNativeAccess = Stopwatch.StartNew();
              var dummyNativeAccess = dummyInstance.DummyMember;
              stopwatchNativeAccess.Stop();
  
              Stopwatch stopwatchGetValueCachedAccess = Stopwatch.StartNew();
              var dummyGetValueCachedAccess = propertyInfo.GetValue(dummyInstance, null);
              stopwatchGetValueCachedAccess.Stop();
  
              Stopwatch stopwatchMethodInfoCachedAccess = Stopwatch.StartNew();
              var dummyMethodInfoCachedAccess = methodInfo.Invoke(dummyInstance, null);
              stopwatchMethodInfoCachedAccess.Stop();
  
              Stopwatch stopwatchDelegateCachedAccess = Stopwatch.StartNew();
              var dummyDelegateCachedAccess = @delegate.DynamicInvoke(dummyInstance);
              stopwatchDelegateCachedAccess.Stop();
  
              Stopwatch stopwatchFuncCachedAccess = Stopwatch.StartNew();
              var dummyFuncCachedAccess = func.Invoke(dummyInstance); // func(dummyInstance);
              stopwatchFuncCachedAccess.Stop();
  
              timeSpanNativeAccess += stopwatchNativeAccess.Elapsed;
              timeSpanGetValueCachedAccess += stopwatchGetValueCachedAccess.Elapsed;
              timeSpanMethodInfoCachedAccess += stopwatchMethodInfoCachedAccess.Elapsed;
              timeSpanDelegateCachedAccess += stopwatchDelegateCachedAccess.Elapsed;
              timeSpanFuncCachedAccess += stopwatchFuncCachedAccess.Elapsed;
          }
  
          Console.WriteLine("timeSpanNativeAccess = " + timeSpanNativeAccess.TotalMilliseconds + " ms");
          Console.WriteLine("timeSpanGetValueCachedAccess = " + timeSpanGetValueCachedAccess.TotalMilliseconds + " ms");
          Console.WriteLine("timeSpanMethodInfoCachedAccess = " + timeSpanMethodInfoCachedAccess.TotalMilliseconds + " ms");
          Console.WriteLine("timeSpanDelegateCachedAccess = " + timeSpanDelegateCachedAccess.TotalMilliseconds + " ms");
          Console.WriteLine("timeSpanFuncCachedAccess = " + timeSpanFuncCachedAccess.TotalMilliseconds + " ms");
  
          Console.ReadKey();
      }
  }
  
  public class DummyClass
  {
      public String DummyMember { get; set; }
  }
  </code></pre>