可以表达式>和destination.x=source.x 被重构吗?

发布于 2024-08-15 09:25:43 字数 2846 浏览 3 评论 0 原文

我正在生成具体实现复印机的接口。后面的步骤是确定我是否可以根据请求的复制类型(直接复制、尝试或 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;
 }
}

我试图用 lambda 来分解一些重复,但来自 这篇帖子似乎只需要一个Expression> 并且我不确定您将如何使用表达式>超载。

一次尝试如下:

 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(z=>z.AddedBy),()=>result.AddedBy=asset.AddedBy}, 满足以下任何条件:

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

I'm generating an interface to concrete implementation copier. A later step will be to determine if I can easily add varying behaviors depending on the copy type requested (straight copy, or try, or try-catch-addToValidationDictionary). This is the main one I need/am working on is the try-catch-addToValidationDictionary. It would be lovely if the copy statements themselves(result.AssetTag = asset.AssetTag) were reusable in list form for another consumer that doesn't need the try/catch/validation functionality.

The General form is this:

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

I'm trying to factor out some of the repetition with lambdas but the Member.Name<IAmAnAsset>(lIAmAnAsset => lIAmAnAsset.AssetTag) from this post seems to only take an Expression<Func<T,object>> and I'm not sure how you would make use of the Expression> overload.

One attempt was as follows:

 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;

I'm hoping for a solution that reduces the duplication inherent in
Member.Name<IAmAnAsset>(z=>z.AddedBy),()=>result.AddedBy=asset.AddedBy},
on any of the following criteria:

  • needing the IAmAnAsset.AddedBy in 2 places on each line
  • needing .AddedBy 3 times on the same line
  • Member.Name<IAmAnAsset> on each and every line
    • Is it possible to have this Expression utilized to retrieve either the string name, or the value of evaluating it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凉宸 2024-08-22 09:25:43

一个简单的函数怎么样?

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

How about a simple function?

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文