具有其他类型的通用Func参数的扩展方法

时间:2013-07-25 21:31:45

标签: linq generics types extension-methods func

有没有办法将泛型方法实现为一个泛型类型,它接受另一个类型的Func参数?

例如,使用类似于此的用法:

myFirstObject.Extension<myOtherObject>( other => other.Prop );

或者使用更复杂的Func:

myFirstObject.Extension<myOtherObject>( other => other.Prop > 2 && other.Prop < 15 );

我发现了一些像this one这样的相关问题,但就我而言,我也需要扩展方法中的泛型类型。

以下是我提出的建议:

public static bool Extension<TSource, TIn, TKey>(this TSource p_Value, Expression<Func<TIn, TKey>> p_OutExpression) 
{ return true; }

但是,当我尝试使用它时,它没有考虑第二种类型。

我错过了什么吗?

3 个答案:

答案 0 :(得分:3)

看看这个:

s => s.Length;

编译器如何知道sstring还是s是一个数组还是其他具有Length属性的类型?它不能,除非你给它一些信息:

(string s) => s.Length;

哦,我们走了。现在,试试这个:

myFirstObject.Extension((myOtherObject o) => o.Prop > 2 && o.Prop < 15);

这样可行,因为你告诉编译器它应该用于TIn,它可以根据表达式找出TKey的用途。

答案 1 :(得分:0)

当您在C#中调用泛型方法时,您可以显式声明所有泛型类型参数,或者可以将它们全部推断出来,但是您不能有一些显式声明和一些推断。

所以,如果我有这个方法:

public void Foo<X, Y>(X x, Y y)
{
    /* Do somethhing */
}

然后这是有效的,有效的是什么:

int a = 42;
string b = "Hello, World!";

// Legal
Foo(a, b);
Foo<int, string>(a, b);

//Illegal
Foo<int>(a, b);

您可以做的最好的事情是将第一个通用参数移到类级别,但不会将它作为扩展方法。不过你可能会喜欢这种方法。

public static class Class<TSource>
{
    public static bool Method<TIn, TKey>(
        TSource p_Value,
        Expression<Func<TIn, TKey>> p_OutExpression) 
    {
        return true;
    }
}

现在你可以这样称呼它:

Expression<Func<long, decimal>> f =
    l => (decimal)l;

var result = Class<int>.Method(a, f);

但正如我所说,它现在不能作为一种扩展方法。

答案 2 :(得分:0)

我发现另一个解决方案是创建另一个接受参数类型的方法。

例如:

Void Extension(Type p_Type, [THE TYPE] p_Params)
{
    MethodInfo realExtensionMethod = typeof([CLASS CONTAINING THE METHOD]).GetMethod("RealExtension");
    realExtensionMethod = realExtensionMethod.MakeGenericMethod(p_Type);
    realExtensionMethod.Invoke(null, new object[] {p_Type, p_Params });
}

Void RealExtension<TYPE>(params)
{

}

然后在使用时间:

Type objectType = typeof(myOtherObject);
myFirstObject.Extension(objectType, other => other.Prop );