Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>UPDATE:</strong> I've finally got this working the right way, please see below.</p> <p><code>DynamicMethod</code> builds a method dynamically at runtime; in the library you are using the method that is created is being added to the object <code>T</code>; however, when <code>T</code> is an interface this fails because you cannot add a method to an interface.</p> <p>The main problem is in the method:</p> <p><code>private static GetPropertyDelegate BuildGetPropertyMethod(PropertyInfo pi)</code></p> <p>as the way this was written it will only work when the collection type <code>T</code> is concrete.</p> <p>If you change the implementation to:</p> <pre><code>private static GetPropertyDelegate BuildGetPropertyMethod(PropertyInfo pi) { MethodInfo getMethod = pi.GetGetMethod(); Debug.Assert(getMethod != null); DynamicMethod dm = new DynamicMethod( "GetProperty_" + typeof(T).Name + "_" + pi.Name, typeof(object), new Type[] { typeof(T) }, pi.Module, true); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.EmitCall(OpCodes.Callvirt, getMethod, null); if (pi.PropertyType.IsValueType) { il.Emit(OpCodes.Box, pi.PropertyType); } // Return the result of the comparison. il.Emit(OpCodes.Ret); return (GetPropertyDelegate)dm.CreateDelegate(typeof(GetPropertyDelegate)); } </code></pre> <p><a href="http://web.archive.org/web/20121028071433/https://www.codingday.com/reflection-for-properties-and-fields-with-dynamicmethod/" rel="nofollow noreferrer">it will work for both concrete types and interfaces</a>.</p> <p>You also need to update the following two methods:</p> <p><code>private static Comparison&lt;T&gt; BuildValueTypeComparison(PropertyInfo pi, ListSortDirection direction)</code></p> <p><code>private static Comparison&lt;T&gt; BuildNullableComparison(PropertyInfo pi, ListSortDirection direction)</code></p> <p>I might be wrong, but I think that the speed gain achieved in these methods comes from the fast property read, so there is not really that much benefit from writing the whole methods using the <code>DynamicMethod</code> method; we can just reuse the <code>BuildGetPropertyMethod</code> from above. So doing this, these become:</p> <pre><code>private static Comparison&lt;T&gt; BuildValueTypeComparison( PropertyInfo pi, ListSortDirection direction) { GetPropertyDelegate m = BuildGetPropertyMethod(pi); Comparison&lt;T&gt; d = delegate(T x, T y) { object mx = m(x); object my = m(y); IComparable c = (IComparable)mx; if (direction == ListSortDirection.Descending) { return -c.CompareTo(my); } return c.CompareTo(my); }; return d; } private static Comparison&lt;T&gt; BuildNullableComparison( PropertyInfo pi, ListSortDirection direction) { GetPropertyDelegate m = BuildGetPropertyMethod(pi); Comparison&lt;T&gt; d = delegate(T x, T y) { object mx = m(x); object my = m(y); IComparable c = (IComparable)mx; if (c == null) { c = (IComparable)my; if (c == null) { return 0; } return direction == ListSortDirection.Descending ? c.CompareTo(mx) : -c.CompareTo(mx); } return direction == ListSortDirection.Descending ? -c.CompareTo(my) : c.CompareTo(my); }; return d; } </code></pre> <p>Obviously do some testing on it, but I'm pretty sure that is what you want and it should be about as fast as the previous code.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload