Only a Curious Mind
Only a Curious Mind

Reputation: 2857

How to pass `params` of a `Func<T>` List with dynamic return?

I need to call a method that receive a list of Func<T>, the problem is that the return of the Func is not the same for all the items of the list.

For example:

//Having the following method:
public void DoSomething(params Expression<Func<T>> list)
{
   //get the property info to get the name and value
   // PropertyInfo p = (propertyExpression.Body as MemberExpression).Member as PropertyInfo;
   //EDIT: Using the answer to change the T to object I needed to get the property info using this: 
   (((UnaryExpression)propertyExpression.Body).Operand as MemberExpression).Member as PropertyInfo;

}

//and the following object
public class Foo
{
    public long Id { get;set; } //LOOK: ITS A LONG PROPERTY
    public string Name { get; set; } // ITS A STRING PROPERTY
}

//I would like to pass these two expressions of DIFFERENT returning types.
Foo f = new Foo();
DoSomething(() => f.Id, () => f.Name); //TWO RETURN TYPES DIFFERENTS.

The compiler says that it's impossible because the method param is a Generic Type T, so all the Funcs passed needs to be the of the same return type.

Upvotes: 0

Views: 576

Answers (3)

user957902
user957902

Reputation: 3060

OK, its not pretty, but I think this is the only way its going to work with generics. It probably not a practical solution:

public void DoSomething<T>(Expression<Func<T>> p)
{

}

public void DoSomething<T1,T2>(Expression<Func<T1>> p1,Expression<Func<T2>> p2)
{

}

public void DoSomething<T1,T2,T3>(Expression<Func<T1>> p1,Expression<Func<T2>> p2,Expression<Func<T3>> p3)
{

}

//etc...

Microsoft does the samae thing with its Func deligates

public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, inT7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, out TResult>(
    T1 arg1,
    T2 arg2,
    T3 arg3,
    T4 arg4,
    T5 arg5,
    T6 arg6,
    T7 arg7,
    T8 arg8,
    T9 arg9,
    T10 arg10,
    T11 arg11,
    T12 arg12,
    T13 arg13,
    T14 arg14
) 

Upvotes: 1

user957902
user957902

Reputation: 3060

One possibility would be to use a fluent interface instead of a list

public object Command
{
    public void DoSomething()
    {
       //do something, act on values stored in member var;
    }

    public Command AddProp<T>(Expression<Func<T>> propAndValue)
    {
       // Get property and value from expression
       // store in member var
       return this;
    }
}



public class Foo
{
    public long Id { get;set; } //LOOK: ITS A LONG PROPERTY
    public string Name { get; set; } // ITS A STRING PROPERTY
}

// Example usage

Foo f = new Foo();
Command cmd = new Command();

cmd.AddProp(() => f.Id).AddProp(() => f.Name).DoSomething();

Upvotes: 0

Jcl
Jcl

Reputation: 28272

Use params Expression<Func<object>>[] list as a parameter, instead of T (note that it must be an array for using with params)

You will, of course, need to cast the result to work with it (unless your process can work with object... say to do a ToString(), for example) inside DoSomething, but how else were you expecting to work with T when T can be different depending on the parameter?

Update: I've made an example in this fiddle, but what you can do with this is pretty much limited, so as @juharr stated in the comments, it'd be better if you explained what do you want to do so we can suggest more practical alternatives

Also, if you don't need the expression (just the callback), there's no need to pass a expression, just pass the Func (modified fiddle)

Upvotes: 2

Related Questions