代码之家  ›  专栏  ›  技术社区  ›  Maslow

表达式<Func<T,object>>和destination.x=source.x是否可以重构?

  •  0
  • Maslow  · 技术社区  · 15 年前

    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的一些重复,但是 Member.Name<IAmAnAsset>(lIAmAnAsset => lIAmAnAsset.AssetTag) 从…起 this 这篇文章似乎只占了上风 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},

    • 需要。在同一行上添加3次
    • Member.Name<IAmAnAsset> 每一行
      • 是否可以使用此表达式来检索字符串名称或对其求值的值?
    1 回复  |  直到 8 年前
        1
  •  0
  •   John Fisher    15 年前

    一个简单的函数怎么样?

    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;
    }