可以表达<func <t,object>&gt;和destination.x = source.x是否重构?</func <t,object>

时间:2009-12-23 16:39:26

标签: c# lambda

我正在为具体的实现复印机生成一个接口。后面的步骤将确定我是否可以根据请求的副本类型(直接复制,或尝试,或try-catch-addToValidationDictionary)轻松添加不同的行为。这是我需要/正在处理的主要是try-catch-addToValidationDictionary。如果复制语句本身(result.AssetTag = asset.AssetTag)可以以列表形式重用于另一个不需要try / catch / validation功能的使用者,那将是很可爱的。

一般表格是:

public static AssetService
{
public static ModelAsset CreateAssetDomain(IAmAnAsset asset, IValidationDictionary validationDictionary)
 {

 var result=new ModelAsset();
 var hasExceptions=false;
  try
        {
            result.AssetTag = asset.AssetTag;
        }
        catch (System.Exception exception)
        {
            validationDictionary.AddError(Member.Name<IAmAnAsset>(lIAmAnAsset => lIAmAnAsset.AssetTag), exception.Message);
            hasExceptions = true;
        }
 try
        {
            result.LocationIdentifer = asset.LocationIdentifer;
        }
        catch (System.Exception exception)
        {
            validationDictionary.AddError(Member.Name<IAmAnAsset>(lIAmAnAsset => lIAmAnAsset.LocationIdentifer), exception.Message);
            hasExceptions = true;
        }
  ...
  if (hasExceptions)
    throw new ArgumentException("Failed validation");

 return result;
 }
}

我试图用lambdas来分解一些重复,但是来自this帖子的Member.Name<IAmAnAsset>(lIAmAnAsset => lIAmAnAsset.AssetTag)似乎只需Expression<Func<T,object>>而且我不确定你会怎样做<表达式的使用>过载。

一次尝试如下:

 Action<Action, Expression<Func<IAmAnAsset, object>>> CopyActions = (copyAction, expression) =>
            {
                try
                {
                    copyAction();
                }
                catch (Exception exception)
                {

                    validationDictionary.AddError(Member.Name<IAmAnAsset>(expression), exception.Message);
                    hasExceptions = true;
                }
            };

  var copyActions = new Dictionary<string,Action>()
    {
    Member.Name<IAmAnAsset>(z=>z.AddedBy),()=>result.AddedBy=asset.AddedBy},
    Member.Name<IAmAnAsset>(z=>z.AssetTag),()=>result.AssetTag=asset.AssetTag},
    ...
    }
 foreach (var item in copyActions)
        {
            tryCopyAction(item.Value, item.Key);
        }
 if (hasExceptions)
throw new ArgumentException("Failed validation");

 return result;

我希望找到一种能够减少内在重复的解决方案  Member.Name<IAmAnAsset>(z=>z.AddedBy),()=>result.AddedBy=asset.AddedBy}, 根据以下任何一项标准:

  • 在每行的2个位置需要IAmAnAsset.AddedBy
  • 需要。在同一行上添加3次
  • 每一行都有
  • Member.Name<IAmAnAsset>
    • 是否可以使用此表达式来检索字符串名称或评估它的值?

1 个答案:

答案 0 :(得分:0)

一个简单的功能怎么样?

public static class Member
{
  private static string GetMemberName(Expression expression)
  {
    switch (expression.NodeType)
    {
      case ExpressionType.MemberAccess: var memberExpression = (MemberExpression)expression; var supername = GetMemberName(memberExpression.Expression); if (String.IsNullOrEmpty(supername)) return memberExpression.Member.Name; return String.Concat(supername, '.', memberExpression.Member.Name);
      case ExpressionType.Call: var callExpression = (MethodCallExpression)expression; return callExpression.Method.Name;
      case ExpressionType.Convert: var unaryExpression = (UnaryExpression)expression; return GetMemberName(unaryExpression.Operand);
      case ExpressionType.Parameter: return String.Empty;
      default: throw new ArgumentException("The expression is not a member access or method call expression");
    }
  }
  public static string Name<T,V>(Expression<Func<T, V>> expression)
  {
    return GetMemberName(expression.Body);
  }
  public static string Name<T>(Expression<Action<T>> expression)
  {
    return GetMemberName(expression.Body);
  }
}

void Copy<D, S, V>(D dest, S source, Expression<Func<S, V>> getVal, Action<D, V> setVal, IDictionary validationDictionary)
{
  Func<S, V> doGetVal = getVal.Compile();
  try { setVal(dest, (V)doGetVal(source)); }
  catch (System.Exception exception)
  {
    validationDictionary.Add(Member.Name<S,V>(getVal), exception.Message);
  }
}

class TestAsset { public string AssetTag { get; set; } public string LocationIdentifier { get; set; } }
TestAsset Test()
{
  Dictionary<string, string> validationDictionary = new Dictionary<string, string>();
  var result = new TestAsset{ AssetTag = "a", LocationIdentifier = "b" };
  var asset = new TestAsset{ AssetTag = "A", LocationIdentifier = "B" };
  var validationCount = validationDictionary.Count(); 
  Copy(result, asset, x => asset.AssetTag, (x, v) => x.AssetTag = v, validationDictionary); 
  Copy(result, asset, x => asset.LocationIdentifier, (x, v) => x.LocationIdentifier = v, validationDictionary); 
  if (validationCount < validationDictionary.Count) throw new ArgumentException("Failed validation"); 
  return result;
}