【问题标题】:How to create attribute to a function that will create a file before or without calling the function如何为将在调用函数之前或不调用函数之前创建文件的函数创建属性
【发布时间】:2017-01-24 04:53:06
【问题描述】:

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

}

【问题讨论】:

  • 你有属性函数可能属于的类列表吗?如果是这样,那么这个问题可能会有用:stackoverflow.com/questions/2831809/…。要获取附加到方法的属性,您需要对该方法所属的类使用反射。
  • 关于您的第一次尝试(将创建文件代码放在属性的构造函数中),这里回答了它不起作用的原因:stackoverflow.com/questions/1168535/…

标签: c# reflection attributes


【解决方案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);
        }
    }
}

【讨论】:

  • 谢谢!有用。我只是做了一点改变,就像你说的那样,只检查一个组件以提高性能。这是我要做的一点改变: var methods = Assembly.GetExecutingAssembly().GetTypes() .SelectMany(t => t.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) .Where(method => Attribute.IsDefined(method, typeof(someAttribute)));
猜你喜欢
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 2016-12-05
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多