我正在为具体的实现复印机生成一个接口。后面的步骤将确定我是否可以根据请求的副本类型(直接复制,或尝试,或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},
根据以下任何一项标准:
Member.Name<IAmAnAsset>
答案 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;
}