简体   繁体   English

使用反射在运行时获取ConditionalAttribute的值

[英]Get value of ConditionalAttribute at runtime using reflection

I am working on a library that involves retrieving the methods of a given type. 我正在研究一个涉及检索给定类型的方法的库。 I have been using Type.GetMethods , but I've noticed an issue. 我一直在使用Type.GetMethods ,但是我注意到了一个问题。 Let's say that a method in the given type uses a ConditionalAttribute , and the value for this condition is false. 假设给定类型的方法使用ConditionalAttribute ,并且该条件的值为false。 GetMethods will still include this method, but I would like to ignore it. GetMethods仍将包含此方法,但我想忽略它。

Here is a simple example of what I am attempting. 这是我正在尝试的一个简单示例。 This program is ran in Debug mode, so I want to find a way where only foo() and fooDebug() are called while fooBar() is ignored. 该程序在Debug模式下运行,因此我想找到一种方法,其中仅foo()和fooDebug()被调用而fooBar()被忽略。

using System;
using System.Diagnostics;
using System.Reflection;

namespace ConsoleApplication
{
    class ClassA
    {
        public static void foo()
        {
            Console.WriteLine("foo");
        }

        [Conditional("DEBUG")]
        public static void fooDebug()
        {
            Console.WriteLine("fooDebug");
        }

        [Conditional("BAR")]
        public static void fooBar()
        {
            Console.WriteLine("fooBar");
        }
    }

    class Program
    {
    //In this example, I want to find a way where only foo() and fooDebug() are called and fooBar() is ignored, when reflected.
        static void Main(string[] args)
        {
            //Call methods directly.
            //Methods are called/ignored as expected.
            ClassA.foo();//not ignored
            ClassA.fooDebug();//not ignored
            ClassA.fooBar();//ignored

            //Call methods with reflection
            MethodInfo[] methods = typeof(ClassA).GetMethods(BindingFlags.Static | BindingFlags.Public);
            foreach (MethodInfo method in methods)
            {
                //All methods are called, regardless of the ConditionalAttribute.
                method.Invoke(null, null);

                //I figured there would be some workaround like this:
                ConditionalAttribute conditional = 
                Attribute.GetCustomAttribute(method, typeof(ConditionalAttribute)) as ConditionalAttribute;

                if (conditional == null)
                {
                    //The method calls if it has no ConditionalAttribute
                    method.Invoke(null, null);
                }
                else
                {
                    //I can get the string of the condition; but I have no idea how, at runtime, to check if it's defined.
                    string conditionString = conditional.ConditionString;

                    //I also cannnot do a hardcoded (conditionString == "BAR") because the library would not know about BAR
                    bool conditionIsTrue = true;
                    //conditionIsTrue = ??

                    //If the method has a ConditionalAttribute, only call it if the condition is true
                    if (conditionIsTrue)
                    {
                        method.Invoke(null, null);
                    }
                }
            }
        }
    }
}

Ultimately, I would like to know which methods do not include false ConditionalAttributes. 最终,我想知道哪些方法不包含错误的ConditionalAttributes。

EDIT 编辑

This idea is for a library that others would use, so assume that ClassA is a type that they define and pass into my library. 这个想法是针对其他人会使用的库,因此假设ClassA是他们定义并传递到我的库中的类型。

What this basically boils down to is: "can I determine, via reflection, the arbitrary conditional compilation symbols that were used to compile a given piece of code" - AFAIK, the answer to that is "no". 基本上可以归结为:“我可以通过反射确定用于编译给定代码段的任意条件编译符号”-AFAIK,答案是“否”。


Note: everything under here no longer applies since the edit that makes it clear that the context here is library / caller. 注意:此处的所有内容均不再适用,因为编辑使该上下文明确为库/调用方。

If you have the luxury of being able to move the methods around (and make them non-public), then maybe: 如果您有足够的能力来移动这些方法(并使它们不公开),那么也许:

partial class Program
{
    static partial void foo();
    static partial void fooDebug();
    static partial void fooBar();

    static partial void foo()
    {
        Console.WriteLine("foo");
    }

#if DEBUG
    static partial void fooDebug()
    {
        Console.WriteLine("fooDebug");
    }
#endif
#if BAR
    static partial void fooBar()
    {
        Console.WriteLine("fooBar");
    }
#endif
    //In this example, I want to find a way where only foo() and fooDebug() are called and fooBar() is ignored, when reflected.
    static void Main(string[] args)
    {
        //Call methods directly.
        //Methods are called/ignored as expected.
        foo();//not ignored
        fooDebug();//not ignored
        fooBar();//ignored

Now, the methods that aren't implemented do not exist after compile, so will not show in the reflection code. 现在,尚未实现的方法在编译后不存在 ,因此不会在反射代码中显示。 Note that you'd need use BindingFlags.Static | BindingFlags.NonPublic 请注意,您需要使用BindingFlags.Static | BindingFlags.NonPublic BindingFlags.Static | BindingFlags.NonPublic to find them now, since they are non-public: BindingFlags.Static | BindingFlags.NonPublic现在可以查找它们,因为它们是非公开的:

MethodInfo[] methods = typeof(Program).GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
foreach (MethodInfo method in methods)
{
    if(method.Name == "Main") continue; // yes, that is lazy
    method.Invoke(null, null);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM