获取扩展方法的被调用者名称

InB*_*een 4 c#

我构建了一个简单的ArgumentValidator类,以简化任何给定方法中的参数前提条件。其中大多数都是null或边界检查,经过几次之后就会变得非常乏味

if (arg == null ) throw new ArgumentNullException(nameof(arg));
Run Code Online (Sandbox Code Playgroud)

所以我提出了以下设置:

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.
}
Run Code Online (Sandbox Code Playgroud)

我可以通过以下方式使用它:

public Bar Foo(object flob)
{
     flob.Validate(nameof(flob)).IsNotNull().IsSmallerThan(flob.MaxValue);
}
Run Code Online (Sandbox Code Playgroud)

nameof(flob)理想情况下,我希望在通话中摆脱Validate并最终完全摆脱Validate;唯一的目的Validate是避免必须将nameof(...)每项检查传递到链条上。

flob有没有办法获取方法内的名称Validate()

Pat*_*man 5

使用扩展方法来做到这一点并不那么容易。使用采用 LINQ 表达式的静态方法会更容易(源自devdigital 的答案此处):

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();
}
Run Code Online (Sandbox Code Playgroud)

里面name是你放入方法中的属性的名称:

MyMethods.Validate(() => o);
Run Code Online (Sandbox Code Playgroud)

由于Validate返回T,您可以进一步使用它。这可能无法达到您想要的效果,但这是唯一可行的选择。

也可以将其作为扩展方法,您必须自己手动创建表达式:

Expression<Func<object>> f = () => o; // replace 'object' with your own type

f.Validate();
Run Code Online (Sandbox Code Playgroud)