views:

44

answers:

2

I'm trying to write an extension method that will give me the MemberInfo representing a member of a given type, using lambda expressions. Ideally, I'd like to be able to write

var info = MyType.GetMember(m => m.MyProperty);

or, also acceptable

var info = typeof(MyType).GetMember(m => m.MyProperty);

or even

var info = typeof(MyType).GetMember((MyType m) => m.MyProperty);

I have a generic method signature that works, but requires me to specify all the type parameters, and I'd very much like C# to infer them. As far as I can see, if I just find the right way to specify the extension method signature, there should be enough information in (at least the last one of) the code snippets to infer everything - but according to the compiler, there isn't.

I've read an old blog post on static extension methods but I haven't been able to find anything on it more recent than that. If that came true, I'd be able to write

public static MemberInfo GetMember<TType, TReturnType>(static TType, Expression<Func<TType, TReturnType>> member)

which would solve my problem. But as I said, I seem to be stuck with instance extensions, in which case

public static MemberInfo GetMember<TType, TReturnType>(this Type t, Expression<Func<TType, TReturnType>> member)

just isn't good enough for the compiler to infer type members.

+2  A: 

How about this:

public static MemberInfo GetMember<TType, TReturnType>
    (this TType ignored,
     Expression<Func<TType, TReturnType>> expression)

which you'd then call like this:

default(MyType).GetMember(m => m.MyProperty)

It's a bit icky, but using default(MyType) is a simple and efficient way of getting an expression of type MyType, which is what you want for type inference.

Jon Skeet
Using `default(MyType)` is actually not really more icky than using `typeof(MyType)`, so it's definitely a good solution. Do you know if static extension methods is considered for any future version of the framework?
Tomas Lycken
But OK, I'm stuck again: when I have this expression, how do I get the actual `MemberInfo` I'm looking for? I'm trying to extract the name of the member I put in (go from `m.MyProperty` to `"MyProperty"`) to use the built-in `GetMember` methods and get the member, but I can't find the correct property of the lambda expression...
Tomas Lycken
@Tomas: Look in the expression tree, and you'll find a MemberExpression which specifies which property to use. I can't give you a sample right now, but basically you need to break down what's in the expression tree until you find what you're looking for.
Jon Skeet
Found it! I needed `((MemberExpression)member.Body).Member`. It's name can be found in the `Name` property, but since I already have the `MemberInfo` there's no need to go via the built-in methods. Thanks!
Tomas Lycken
A: 

If you don't have an instance, I think the best you can do is:

public static MemberInfo GetMember<TType, TReturnType>(Expression<Func<TType, ReturnType>> member)

Then use like this:

MemberInfo info = YourClass.GetMember((YourConcreteType instance) => instance.Property);

You can keep an overload that takes an instance as the first argument, so you can use extension method syntax whenever you have an instance:

public static MemberInfo GetMember<TType, TReturnType>(this TType instance, Expression<Func<TType, ReturnType>> member)

Then use like this:

MemberInfo info = yourInstanceOfTType.GetMember(instance => instance.Property);
driis