与MemberInit表达式的性能差异

编程入门 行业动态 更新时间:2024-10-25 01:27:27
本文介绍了与MemberInit表达式的性能差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在处理与问题222511 类似的问题需要使用MemberInit表达式,这样我就可以将它们添加到构造函数中...我正在尝试实现 John Skeet的答案,但是我遇到了很大的性能差异.这是一些代码:

I am working a similar problem as Question 222511 I do need to use the MemberInit Expression so I can just add them to the constructor... I am trying to implement John Skeet's answer but I am running into a big performance difference. Here is some of the code:

// Method A: // This work good, is fast and returns an un-executed query... DataContext.LoanNote.Join<LoanNote, Customer, int, LoanNote>( DataContext.Customers, loanNote => loanNote.PrimaryCustomerNumber, customer => customer.CustomerNumber, (LoanNote loanNote, Customer customer) => new LoanNote() { AccountFeeBillAmount = loanNote.AccountFeeBillAmount, AccountOpenDate = loanNote.AccountOpenDate, // This goes on and on... PrimaryCustomer = customer }); // Method B: // This on the other hand is a lot slower and I am not sure why... var resultSelector = BuildJoinResultSelector<LoanNote, Customer, LoanNote("PrimaryCustomer").Compile(); DataContext.LoanNote.Join<LoanNote, Customer, int, LoanNote>( DataContext.Customers, loanNote => loanNote.PrimaryCustomerNumber, customer => customer.CustomerNumber, resultSelector); // The build MemberInitExpression method... private static Expression<Func<TOuter, TInner, TResult>> BuildJoinResultSelector<TOuter, TInner, TResult>(string propertyName) where TResult : class { var result = default(Expression<Func<TOuter, TInner, TResult>>); var resultType = typeof(TResult); var outerType = typeof(TOuter); var innerType = typeof(TInner); var outer = Expression.Parameter(outerType, "outer"); var inner = Expression.Parameter(innerType, "inner"); var bindings = new List<MemberBinding>(); foreach (var property in resultType.GetProperties()) { if (property.CanRead == false) { continue; } else if (property.CanWrite == false) { continue; } else if (property.Name == propertyName) { var condition = Expression.Condition(Expression.Equal(inner, Expression.Constant(null)), Expression.New(innerType), inner); bindings.Add(Expression.Bind(property, condition)); } else { bindings.Add(Expression.Bind(property, Expression.Property(outer, property))); } } var memberInit = Expression.MemberInit(Expression.New(resultType), bindings); result = Expression.Lambda<Func<TOuter, TInner, TResult>>(memberInit, outer, inner); return result; }

推荐答案

第二种方法执行起来较慢,因为它使用了反射(GetProperties调用).

The second method will be slower to execute because it uses reflection (the GetProperties call).

如果您多次调用它,则可以像这样缓存GetProperties的结果:

If you are calling it many times, you can cache the result of GetProperties like this:

static class PropertiesCache<T> { public static readonly PropertyInfo[] Properties = typeof(T).GetProperties(); }

这将对每种类型仅调用一次GetProperties;像这样使用:

This will call GetProperties just once per type; use like this:

foreach (var property in PropertiesCache<TResult>.Properties) { if(!property.CanRead || !property.CanWrite) continue; //... }

编辑:

您还可以将整个循环替换为LINQ查询,如下所示:

You can also replace your entire loop with a LINQ query, like this:

var memberInit = Expression.MemberInit(Expression.New(typeof(TResult)), from property in PropertiesCache<TResult>.Properties where property.CanRead && property.CanWrite select Expression.Bind(property, property.Name == propertyName ? Expression.Coalesce(inner, Expression.New(innerType)) : Expression.Property(outer, property) ) );

更多推荐

与MemberInit表达式的性能差异

本文发布于:2023-10-16 05:59:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1496693.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:表达式   差异   性能   MemberInit

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!