2017-01-23 7 views
1

Мне нужно создать атрибут для функций, которые будут создавать файлы в соответствии с заданным именем до вызов функции или даже если есть нет вызова функции.
Например, если у меня есть функция с atribute [some("C:\\hello.txt")]:Как создать атрибут функции, которая создаст файл до или без вызова функции

[some("C:\\hello.txt")] 
private void foo() 
{ 
    // do something 
} 

Когда я запустить приложение будет создавать этот файл («C: \ hello.txt») перед вызовом функции или даже если нет никакого вызова функции ..

Я попытался с двумя методами:
1. Создание файла в конструкторе
2. Создание файла с отражением.

Но никто из них не работал для меня.

Первая попытка (с конструктором):
Я пытался создать файл в конструкторе каждый раз, когда есть новый атрибут.
В этом методе я попытался создать файл до ввода функции Main.
Пока он анализирует функции, он найдет атрибуты и создаст файлы.
Ожидаемое:
Два файлы должны быть созданы:
1. C: \ hello.txt
2. C: \ bye.txt

В действительности => ничего не происходит.

[some("C:\\hello.txt")] 
private void foo() 
{ 
    // do something 
} 

[some("C:\\bye.txt")] 
private void foo() 
{ 
    // do something 
} 

public class someAttribute : Attribute 
{ 
    public someAttribute(string fileToCreate) 
    { 
     // File.Create(fileToCreate); 
     Console.WriteLine("Create file " + fileToCreate); 
    } 
} 

static void Main(string[] args) 
{ 
    // something 
} 

Вторая попытка (с отражением):
Ожидаемое:
Один файл должен быть создан:
1. C: \ hello.txt

В действительности => "типы" переменных пуст и ничего не создается.

[some(fileToCreate = "C:\\hello.txt")] 
private void foo() 
{ 
    // do something 
} 

public class someAttribute : Attribute 
{ 
    public string fileToCreate {get; set;} 
} 

static void Main(string[] args) 
{ 

    var types = from t in Assembly.GetExecutingAssembly().GetTypes() 
       where t.GetCustomAttributes<someAttribute>().Count() > 0 
       select t; 
    foreach(var t in types) // types is null 
    { 
     string n = t.Name; 
     foreach(var p in t.GetProperties()) 
     { 
      // File.Create(fileToCreate) 
      Console.WriteLine(p.fileToCreate); 
     } 
    } 

} 
+0

У вас есть список классов, к которым могут относиться атрибутивные функции? Если это так, то этот вопрос может быть полезен: http://stackoverflow.com/questions/2831809/how-would-i-use-reflection-to-call-all-the-methods-that-has-a-ertain- заказ АТТ. Чтобы получить атрибуты, привязанные к методу, вам нужно будет использовать отражение класса, к которому принадлежит метод. – purplecat

+0

Что касается вашей первой попытки (поместив код созданного файла в конструктор атрибута), причина, по которой она не сработала, ответила здесь: http://stackoverflow.com/questions/1168535/when-is-a-custom-attributes -constructor перспективе # 1168590. – purplecat

ответ

1

Ваша первая попытка не работает, потому что конструктор атрибута выполняется, когда атрибут рассматривается См When is a custom attribute's constructor run? для получения дополнительной информации. Он не будет запускаться только из-за того, что метод имеет этот атрибут в коде. Поэтому для получения списка методов, имеющих желаемый атрибут, потребуется отражение.

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

Я придумал решение, но предупреждаю, что это может повлиять на производительность, поскольку оно рассматривает каждый тип и метод в сборках, связанных с вашим проектом. Возможно, вы захотите ограничить сборку только теми, которые вы можете ожидать, someAttribute. См. C#: List All Classes in Assembly для некоторых примеров того, как это сделать.

static void Main() 
{ 
    var methods = AppDomain.CurrentDomain.GetAssemblies() 
        //Get a sequence of all types in the referenced assemblies 
        .SelectMany(assembly => assembly.GetTypes()) 
        //Get a sequence of all the methods in those types. 
        //The BindingFlags are needed to make sure both public and non-public instance methods are included. 
        //Otherwise private methods are skipped. 
        .SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) 
        //And finally, filter to only those methods that have someAttribute attached to them 
        .Where(method => Attribute.IsDefined(method, typeof(someAttribute))); 

    foreach (MethodInfo methodInfo in methods) 
    { 
     IEnumerable<someAttribute> SomeAttributes = methodInfo.GetCustomAttributes<someAttribute>(); 
     foreach (var attr in SomeAttributes) 
     { 
      //Here, you can create the file. 
      Console.WriteLine(attr.fileToCreate); 
     } 
    } 
} 
+0

Спасибо! Оно работает. Я только немного изменился, как вы сказали, чтобы пройти только одну сборку для исполнения. Это мое небольшое изменение для этого: var methods = Assembly.GetExecutingAssembly(). GetTypes() .SelectMany (t => t.GetMethods (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) . Где (метод => Attribute.IsDefined (метод, typeof (someAttribute))); – E235

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

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