如何为在调用函数之前或不调用函数时创建文件的函数创建属性

时间:2017-01-23 18:09:50

标签: c# reflection attributes

我需要为函数创建属性,这些函数将根据给定名称创建文件调用函数,或者即使没有调用函数
例如,如果我具有属性[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

实际上=> “types”变量为空,没有创建任何内容。

[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);
        }
    }

}

1 个答案:

答案 0 :(得分: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);
        }
    }
}