2013-07-29 7 views
1

Я работаю над библиотекой, которая включает в себя получение методов заданного типа. Я использовал Type.GetMethods, но я заметил проблему. Предположим, что метод в данном типе использует ConditionalAttribute, а значение для этого условия ложно. GetMethods по-прежнему будет включать этот метод, но я хотел бы проигнорировать его.Получить значение ConditionalAttribute во время выполнения с помощью отражения

Вот простой пример того, что я пытаюсь. Эта программа запускается в режиме отладки, поэтому я хочу найти способ, в котором вызывается только 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); 
        } 
       } 
      } 
     } 
    } 
} 

В конечном счете, я хотел бы знать, какие методы не включают ложные условные атрибуты.

EDIT

Эта идея для библиотеки, что другие будут использовать, так предположить, что ClassA является типом, который они определяют и передают в моей библиотеке.

+0

Вы можете получить тело метода с помощью отражения и проверить, если он пуст. –

+0

@TobiasBrandt: ложный условный атрибут не делает метод пустым. Метод полностью скомпилирован, но прямые вызовы к нему игнорируются. – Rubixus

+0

Игнорируется в каком смысле? У методов есть какой-то маркер, чтобы сообщить исполняемой программе не выполнять их? –

ответ

1

Что это в основном сводится к: «Могу ли я определить через отражение произвольные условные символы компиляции, которые использовались для компиляции данной части кода» - AFAIK, ответ на этот вопрос «нет».


Примечание: все, что здесь отсутствует, больше не применяется, поскольку редактирование дает понять, что здесь контекст является библиотекой/вызывающим.

Если у вас есть роскошь быть в состоянии двигаться методы вокруг (и сделать их непубличный), то возможно:

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 

Теперь, методы, которые не реализованы не существует после компиляции, поэтому не будет отображаться в коде отражения. Обратите внимание, что вам нужно использовать 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); 
} 
+0

'Rubixus' эта ссылка может помочь в предоставлении дополнительной информации Marc answer [MSDN C# Conditional] (http://msdn.microsoft.com/en-us/library/4xssyw96%28VS.80%29.aspx) – MethodMan

+0

Я рассмотрел это, но эта идея предназначена для библиотеки, которую другие будут использовать, и я хотел бы ограничить требования для их использования. Поэтому, если они определяют тип с условным атрибутом, они должны предположить, что моя библиотека будет игнорировать его, когда он является ложным. – Rubixus

+0

@Rubixus, если это для библиотеки, обратите внимание, что вы не можете использовать 'partial' в любом случае, который испаряется и не существует в IL. Я не думаю, что ваш код может определить, какие условные символы компиляции используются в произвольном коде; Я подозреваю, что вы можете добавить ** отдельный ** атрибут, который они могут использовать для указания методов, которые должны быть включены/исключены –

 Смежные вопросы

  • Нет связанных вопросов^_^