【问题标题】:Extension method with generic Func parameter of other type具有其他类型的泛型 Func 参数的扩展方法
【发布时间】:2013-07-25 21:31:45
【问题描述】:

有没有办法实现一个泛型类型的扩展方法,它接受另一个类型的 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; }

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

我错过了什么吗?

【问题讨论】:

    标签: linq generics types extension-methods func


    【解决方案1】:

    看看这个:

    s => s.Length;
    

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

    (string s) => s.Length;
    

    哦,我们开始了。所以现在,试试这个:

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

    这会起作用,因为您已经告诉编译器它应该为TIn 使用什么,它可以根据表达式计算出对于TKey 使用什么。

    【讨论】:

      【解决方案2】:

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

      例如:

      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 );
      

      【讨论】:

        【解决方案3】:

        当您在 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);
        

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

        【讨论】:

        • 我可以使用它的组合来创建一个调用另一种方法的扩展,这应该可以工作。我会发布我的结果。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多