开发者

Why not a memberinfo() reflection function for C# [duplicate]

开发者 https://www.devze.com 2023-01-25 20:00 出处:网络
This question already has answers here: Why is there not a `fieldof` or `methodof` operator in C#? [closed]
This question already has answers here: Why is there not a `fieldof` or `methodof` operator in C#? [closed] (4 answers) Closed 9 years ago.

There is sizeof() and typeof(), but why not a memberinfo() returning an instance of System.Reflection.MemberInfo for the part of code selected in order to aid in reflection code.

Example:

Program() 
{
       Type t = typeof(Foo);

       Foo foo = new Foo();
       PropertyInfo pi = memberinfo(Foo.Name) as PropertyInfo;
       // or shall it be like this
       // PropertyInf开发者_开发问答o pi = memberinfo(foo.Name) as PropertyInfo;

       string name = pi.GetValue(foo, null);
}

I am trying to understand if there is a fundamental reason why this could be implemented in the C# spec.

I am not bashing anything, I am just doing some wishful thinking, so be kind please.


Eric Lippert talks about this extensively on his blog

To quote directly from that post:

Just off the top of my head, here are a few {reasons why this hasn't been done}. (1) How do you unambiguously specify that you want a method info of an specific explicit interface implementation? (2) What if overload resolution would have skipped a particular method because it is not accessible? It is legal to get method infos of methods that are not accessible; metadata is always public even if it describes private details. Should we make it impossible to get private metadata, making the feature weak, or should we make it possible, and make infoof use a subtly different overload resolution algorithm than the rest of C#? (3) How do you specify that you want the info of, say, an indexer setter, or a property getter, or an event handler adder?


There are a couple of items which make this type of feature difficult. One of the primary ones being overloaded methods.

class Example { 
  public void Method() {}
  public void Method(int p1) {}
}

Which MethodInfo would the following return?

var info = memberinfo(Example.Method);

As Wesley has pointed out though, Eric Lippert's Blog has the full discussion on this issue.


There are numerous reasons why compile-time member reflection has not yet been implemented in C# - but most of them basically boil down to opportunity cost - there are many other languages features and enhancements that offer more benefit to more users. There's also the consideration that an infoof syntax could be complicated, confusing, and ultimately less powerful than using string-based reflection. It also wouldn't be a complete replacement for reflection since in many instances the metadata being manipulated isn't known at compile time.

However, all is not lost, there are a number of tricks that you can employ to perform slightly safer reflection that leverages capabilities of the C# language. For instance, we can take advantage of lambda expressions and expression trees to extract MemberInfo information. A simple example is:

public static class MethodExt {
    static MethodInfo MemberInfo(Action d) {
       return d.Method;
    }
    // other overloads ...
}

which works when you pass in a (non-anonymous) action delegate:

MethodInfo mi = MethodExt.MemberInfo( Object.ToString );

An implementation of the above using expression trees can more robust and flexible, but also substantially more complicated. It could be used to represent member and property access, indexers, etc.

The main issue with all such "fancy" approaches, is that they are confusing to developers who are used to seeing traditional reflection code. They also can't handle all cases, which often results in an unfortunate mixture of traditional reflection code and fancy expression tree code. Personally, while such techniques are interesting and inventive, it's probably best to avoid it in production code.


I myself use an approach that reads the IL from an anonymous method (using Mono.Reflection namespace) and grabs the info of the last token found in the anonymous method. This tends to be the only way to get information about things like the add_EventHandler or set_Property or captured local variables. To actual get properties I use expression trees.

The syntax that I use is Reflect.Member<T>.InfoOf<TMember>(Func<T,TMember> memberfunc) where Member is replaced with the type I'm interested in. It's verbose sure, but it lets a user know exactly what the code is trying to do. I also have Reflect.Member styles for things like statics and constructors. Here is the relevant code snippet::

internal static MemberInfo GetLastMemberOfType(MethodBase method, MemberTypes memberType)
    {
        var instructions = method.GetInstructions();
        var operandtype = memberType == MemberTypes.Field ? OperandType.InlineField : OperandType.InlineMethod; 
        for (int i = instructions.Count-1; i > -1 ; i--)
        {
            if (instructions[i].OpCode.OperandType == operandtype)
            {
                return instructions[i].Operand as MemberInfo;
            }
        }
        return null;
    }

Does it replace string based reflection? Absolutely not. Does it make my code safer while I'm refactoring interfaces and what not? Absolutely. Will it ship with the product I'm working on? Probably not.

0

精彩评论

暂无评论...
验证码 换一张
取 消