扩展方法帮助

时间:2009-03-09 18:28:31

标签: c# .net

我正在编写一个扩展方法,我碰巧需要在扩展方法中需要扩展方法的字段名称。我无法弄清楚如何做到这一点。

我的代码:


扩展方法:

public static Validate Demand<T>(this T parameter)
{
    string name = ...
    var field = GetField(parameter);
    return Validation.CreateValidation(parameter, field, name);
}

用例:

void SomeMethod(T someParameter)
{
   someParameter.Demand();
}

我希望name能够someParameter

2 个答案:

答案 0 :(得分:1)

你做不到。在少数情况下会很好,特别是对于参数检查,但这是不可能的。作为一个方便的例子,我有这个方法:

internal static void ThrowIfNull<T>(this T argument, string name)
    where T : class
{
    if (argument == null)
    {
        throw new ArgumentNullException(name);
    }
}

我必须致电:

foo.ThrowIfNull("foo");

总比没有好,但是不必提供“foo”位就好了。不幸的是,没有办法做到这一点。你可能会编写一个构建后的IL重写器,它确定了如何调用该方法并从中重建它,但我认为这比利益更多,我怀疑:)

答案 1 :(得分:0)

这是获得我认为你要求的一种方式:

static class Argument
{
    public static void NotNull(Expression<Func<Func<object>>> arg)
    {
        if (arg.Compile()()() == null)
        {
            var body1 = (Expression<Func<object>>)arg.Body;
            var body2 = (MemberExpression)body1.Body;
            throw new ArgumentNullException(body2.Member.Name);
        }
    }
}

像这样使用:

void F(string foo)
{
    Argument.NotNull(() => () => foo);

关于这一点的好处是在IDE中重命名foo将获得所有引用。 (如果字符串中有foo,则会遗漏。)

如果在紧密循环中使用它,可能会导致性能问题,因为它每次都会调用.Compile()()。您可以通过添加此重载来优化性能:

    public static void NotNull(object value, Expression<Func<Func<object>>> arg)
    {
        if (value == null)
        {
            var body1 = (Expression<Func<object>>)arg.Body;
            var body2 = (MemberExpression)body1.Body;
            throw new ArgumentNullException(body2.Member.Name);
        }
    }

使用方法如下:

Argument.NotNull(foo, () => () => foo);

它仍然可以重命名,并且每次迭代都会保存该调用。

我建议您在编写代码时使用第一个版本,然后在分析器下运行,并在重要情况下切换到第二个版本。