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