如何在重载方法中传递各种表达式函数

本文关键字:表达式 函数 重载 方法 | 更新日期: 2023-09-27 18:01:00

我需要一个类似的方法:

// takes in a DefaultValue type as an Expression Function, with an argument
public void Register<T, TDefaultValueArgs>(Expression<Func<TDefaultValueArgs, T>> defaultValue)
{
    // stuff happens here.....
}

我想添加该方法的两个重载版本。一个是defoutlValue是T的简单实例,另一个是defaultValue是不带参数的表达式函数。

我想出了这个(未经测试的(解决方案:

// takes in a DefaultValue type
public void Register<T>(T defaultValue)
{
    // The statement below would be better, but isn't valid: "A lambda expression with a statement body cannot be converted to an expression tree"
    // Expression<Func<object, T>> defaultValueFunc = (o) => { return defaultValue; };
    Expression<Func<DefaultValueContainer<T>, T>> defaultValueFunc = (m => m.GetDefaultValue(defaultValue));
    Register<T, DefaultValueContainer<T>>(defaultValueFunc);
}
// takes in a DefaultValue type as an Expression Function
public void Register<T>(Expression<Func<T>> defaultValue)
{
    // The statement below would be better, but isn't valid: "A lambda expression with a statement body cannot be converted to an expression tree"
    // Expression<Func<object, T>> defaultValueFunc = (o) => { return defaultValue.Compile().Invoke(); };
    Expression<Func<DefaultValueContainer<T>, T>> defaultValueFunc = (m => m.GetDefaultValue(defaultValue));
    Register<T, DefaultValueContainer<T>>(defaultValueFunc);
}
private class DefaultValueContainer<T>
{
    public DefaultValueContainer()
    { }
    public T GetDefaultValue(T defaultValue)
    {
        return defaultValue;
    }
    public T GetDefaultValue(Expression<Func<T>> defaultValue)
    {
        return defaultValue.Compile().Invoke();
    }
}

然后我假设,在我最初的Regsiter<T, TDefaultValueArgs>方法中,我可以做这样的事情:

T resolvedDefaultValue = default(T);
if (typeof(TDefaultValueArgs).Equals(typeof(DefaultValueContainer<T>)))
{
    var defaultValueContainer = Activator.CreateInstance<TDefaultValueArgs>();
    resolvedDefaultValue = defaultValue.Compile().Invoke(defaultValueContainer);
}

所有这些,包括DefaultValueContainer<T>的使用,似乎都很愚蠢。一定有更好的方法吗?

注意:由于本示例范围之外的原因,我需要使用表达式类型,而不仅仅是委托。

如何在重载方法中传递各种表达式函数

您可以将您的lambda更改为表达式lambda,而不需要包装器类。

你想要的代码(但不起作用(:

Expression<Func<object, T>> defaultValueFunc =
                            (o) => { return defaultValue; };

你应该拥有的:

Expression<Func<object, T>> defaultValueFunc = 
                            (o) => defaultValue;

类似地,代替:

Expression<Func<object, T>> defaultValueFunc =
                            (o) => { return defaultValue.Compile().Invoke(); };

你应该有:

Expression<Func<object, T>> defaultValueFunc =
                            (o) => defaultValue.Compile().Invoke();

进行这些更改应该允许您使用原始的Register<T>方法。

此外,我不确定这是否只是写问题时的错误,但您可能希望对齐原始方法中的泛型类型参数,以便它们与Func<>的顺序相同参数。不过,这只是一种风格上的狡辩。