Question

Is there a way to implement an extension method to a generic type that takes in arguments a Func of another type?

For exemple, a usage something similar to this:

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

Or with a more complicated Func:

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

I found some related question like this one, but in my case, I need generic types inside the extension method too.

Here's what I came up with:

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

However, when I try to use it, it does not take into consideration the second type.

Am I missing something?

Was it helpful?

Solution

Look at this:

s => s.Length;

How's the compiler suppose to know whether or not s is a string or s is an array or some other type that has a Length property? It can't, unless you give it some information:

(string s) => s.Length;

Oh, there we go. So now, try this:

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

That will work, because you've told the compiler what it should use for TIn, and it can figure out what to use for TKey based on the expression.

OTHER TIPS

I found that another solution would be to create another method that takes in argument a type.

For instance:

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

}

Then at usage time:

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

When you call a generic method in C# you can explicitly declare all of the generic type parameters or you can have them all inferred, but you cannot have some explicitly declared and some inferred.

So, if I had this method:

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

Then here's what works and what doesn't:

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

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

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

The best you can do is move the first generic parameter up to the class level, but not it won't work as an extension method. Nevertheless you may like this approach.

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

Now you can call it like this:

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

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

But as I say, it won't work as an extension method now.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top