32

私はこのクラスを取得しました

public class fooBase
{
    public List<MethodsWithCustAttribute> MethodsList;
    public bool fooMethod([CallerMemberName]string membername =""))
    {
        //This returns a value depending of type and method 
    } 
    public void GetMethods()
    {
        // Here populate MethodsList using reflection
    }
}

そしてこの属性クラス

// This attribute get from a database some things, then fooMethod check this attribute members 
public class CustomAttribute
{
    public string fullMethodPath;
    public bool someThing ; 
    public bool CustomAttribute([CallerMemberName]string membername ="")
    {
        fullMethodPath = **DerivedType** + membername 
        //  I need here to get the type of membername parent. 
        //  Here I want to get CustClass, not fooBase

    }
}

それから私はこれを持っています

public class CustClass : fooBase
{
     [CustomAttribute()]
     public string method1()
     {
         if (fooMethod())
         {
             ....
         }
     }
}

CallerMember の Type 名が必要です。Caller のクラス所有者の Type を取得するには [CallerMemberName] のようなものがありますか?

4

3 に答える 3

6

より良い解決策については、編集 2を参照してください。

私の意見では、提供される情報CompilerServicesは少なすぎて、呼び出し元のメソッドから型を取得できません。あなたができることは、StackTraceを参照)を使用して呼び出し元のメソッドを見つけ(を使用してGetMethod())、そこから使用して型を取得するReflectionことです。
次の点を考慮してください。

using System.Runtime.CompilerServices;

public class Foo {
    public void Main() {
        what();
    }

    public void what() {
        Bar.GetCallersType();
    }

    public static class Bar {

        [MethodImpl(MethodImplOptions.NoInlining)]  //This will prevent inlining by the complier.
        public static void GetCallersType() {
            StackTrace stackTrace = new StackTrace(1, false); //Captures 1 frame, false for not collecting information about the file
            var type = stackTrace.GetFrame(1).GetMethod().DeclaringType;
            //this will provide you typeof(Foo);
        }
    }
}

注意 - @Jay がコメントで言ったように、かなり高価かもしれませんが、うまく機能します。

編集:

パフォーマンスを比較しているいくつかのアークティクルを見つけましたが、実際に比較して恐ろしく高価であり、Reflectionどちらも最高ではないと考えられています。
参照: [1] [2]

編集2:

そのため、詳細に調べた後、StackTrace実際に使用するのは安全ではなく、高価です.
呼び出されるすべてのメソッドは でマークされるため[CustomAttribute()]、それを含むすべてのメソッドを静的リストに集めることができます。

public class CustomAttribute : Attribute {
    public static List<MethodInfo> MethodsList = new List<MethodInfo>();
    static CustomAttribute() {
        var methods = Assembly.GetExecutingAssembly() //Use .GetCallingAssembly() if this method is in a library, or even both
                  .GetTypes()
                  .SelectMany(t => t.GetMethods())
                  .Where(m => m.GetCustomAttributes(typeof(CustomAttribute), false).Length > 0)
                  .ToList();
        MethodsList = methods;
    }

    public string fullMethodPath;
    public bool someThing;

    public  CustomAttribute([CallerMemberName] string membername = "") {
        var method = MethodsList.FirstOrDefault(m=>m.Name == membername);
        if (method == null || method.DeclaringType == null) return; //Not suppose to happen, but safety comes first
        fullMethodPath = method.DeclaringType.Name + membername; //Work it around any way you want it
        //  I need here to get the type of membername parent. 
        //  Here I want to get CustClass, not fooBase
    }
}

このアプローチを試して、正確なニーズに合わせてください。

于 2013-07-27T03:32:36.107 に答える