我已经构建了一个简单的ArgumentValidator
类,以简化任何给定方法中的参数前置条件。它们中的大多数都是null
或边界检查,经过几次
if (arg == null ) throw new ArgumentNullException(nameof(arg));
所以我想出了以下设置:
public static class ArgumentValidator
{
public interface IArgument<T>
{
string ParamName { get; }
T Value { get; }
}
private class Argument<T>: IArgument<T>
{
public Argument(T argument, string paramName)
{
ParamName = paramName;
Value = argument;
}
public string ParamName { get; }
public T Value { get; }
}
public static IArgument<T> Validate<T>(this T argument, string paramName = null)
{
return new Argument<T>(argument, paramName ?? string.Empty);
}
public static IArgument<T> IsNotNull<T>(this IArgument<T> o)
{
if (ReferenceEquals(o.Value, null))
throw new ArgumentNullException(o.ParamName);
return o;
}
public static IArgument<T> IsSmallerThan<T, Q>(this IArgument<T> o, Q upperBound) where T : IComparable<Q> { ... }
//etc.
}
我可以通过以下方式使用它:
public Bar Foo(object flob)
{
flob.Validate(nameof(flob)).IsNotNull().IsSmallerThan(flob.MaxValue);
}
理想情况下,我希望在nameof(flob)
电话中摆脱Validate
,最终完全摆脱Validate
; Validate
的唯一目的是避免在链上的每次检查中都必须通过nameof(...)
。
有没有办法在flob
方法中获取名称Validate()
?
答案 0 :(得分:3)
使用扩展方法做到这一点并不容易。使用带有LINQ表达式(源自devdigital's answer here)的静态方法更容易:
.class
public static T Validate<T>(this Expression<Func<T>> argument)
{
var lambda = (LambdaExpression)argument;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else
{
memberExpression = (MemberExpression)lambda.Body;
}
string name = memberExpression.Member.Name;
Delegate d = lambda.Compile();
return (T)d.DynamicInvoke();
}
inside是您在方法中输入的属性的名称:
name
由于MyMethods.Validate(() => o);
返回Validate
,您可以进一步使用它。这可能没有你想要的那样,但这是唯一可行的选择。
也可以将其作为扩展方法,您必须自己手动创建表达式:
T