我正在编写一个服务,在
CSV Format中将特定类型的对象集合和
output its primitive,string,and DateTime types作为字符串.我有以下两个语句都可以正常工作.我发现基于lambda的版本更清洁.
魔术弦版
string csv = new ToCsvService<DateTime>(objs) .Exclude("Minute") .ChangeName("Millisecond","Milli") .Format("Date","d") .ToCsv();
与Lambda版本
string csv = new ToCsvService<DateTime>(objs) .Exclude(p => p.Minute) .ChangeName(p => p.Millisecond,"Milli") .Format(p => p.Date,"d") .ToCsv();
根据Jon Skeet的建议,所有lambda方法都共享一个类似的方法签名
public IToCsvService<T> Exclude<TResult>( Expression<Func<T,TResult>> expression)
然后我将表达式.Body传递给FindMemberExpression.我已经从nhlambdaextensions project改编了FindMemberExpression
method of ExpressionProcessor.cs的代码.我的FindMemberExpression非常相似的版本如下:
private string FindMemberExpression(Expression expression) { if (expression is MemberExpression) { MemberExpression memberExpression = (MemberExpression)expression; if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess || memberExpression.Expression.NodeType == ExpressionType.Call) { if (memberExpression.Member.DeclaringType.IsGenericType && memberExpression.Member.DeclaringType .GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { if ("Value".Equals(memberExpression.Member.Name)) { return FindMemberExpression(memberExpression.Expression); } return String.Format("{0}.{1}",FindMemberExpression(memberExpression.Expression),memberExpression.Member.Name); } } else { return memberExpression.Member.Name; } } throw new Exception("Could not determine member from " + expression.ToString()); }
我在FindMemberExpression中测试了足够多的案例?鉴于我的用例,我正在做什么矫枉过正?
解决方法
编辑:使这个更简单的核心是将方法的签名更改为结果类型中的通用:
public IToCsvService<TSource> Exclude<TResult>( Expression<Func<TSource,TResult>> expression)
这样您就不会得到转换表达式,因为不需要转换.例如,p => p.Minute将以表达式< Func< DateTime,int>>结束.由于类型推断自动.
对我来说这看起来有点矫枉过正,因为目前您需要的只是一个属性 – 至少,这就是您的样本所展示的一切.
为什么不从识别属性开始,如果需要,可以在以后扩展它?
编辑:这是一个简短但完整的示例,不显示任何转换:
using System; using System.Linq.Expressions; class Test { static void Main() { Expression<Func<DateTime,int>> dt = p => p.Minute; Console.WriteLine(dt); } }
如果将表达式类型更改为Expression< Func< DateTime,long>>但是,它确实显示了Convert(…)位.我怀疑您需要更改Exclude(etc)方法的签名.