我在研究attributes
using System;
public class HelpAttribute : Attribute
{
public HelpAttribute(String Descrition_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
[Help("this is a do-nothing class")]
public class AnyClass
{
}
我怀疑的是,当使用this
关键字时。
我们知道,this
指的是当前对象。
我在这里看不到任何对象?
constructor
如何在这里真正起作用?
答案 0 :(得分:4)
我在这里看不到任何对象?
嗯,有。当您使用反射从AnyClass
请求属性时,它会使用指定的参数创建属性的新实例。
实际上,该属性将像任何其他类一样创建,只是语法与指定属性不同。
请注意,不会在AnyClass
!
Type t = typeof(AnyClass);
HelpAttribute[] attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
.Cast<HelpAttribute>()
.ToArray(); // on this line the attribute is instantiated
Console.WriteLine(attributes.FirstOrDefault()?.Description);
答案 1 :(得分:2)
我喜欢已经给出的答案,只想在那里多加一点;不要将此标记为答案,只需在需要时将其用作帮助者。
该属性不会成为课程的一部分,它只是与课程联系在一起。换句话说,使用AnyClass
的任何人都不会关心或了解HelpAttribute
,除非他们特别想要/需要知道;当他们这样做时,他们会使用像帕特里克的答案中列出的代码来获取这些信息。
常见的问题是为什么要使用它们以及如何正确使用它们。只需记住属性并非真正修改属性的任何现有对象,而是用于编译和其他关心使用属性的对象。我要发一个例子。
注意:此示例仅用于教育目的。
在此示例通知中,有两种方法可以调用worker。第一个运行工作人员而不关心属性,第二个按自定义PriorityAttribute
命令工作人员。另外,我道歉这是一个文件,这不是理想的。我只是这样做,以便在这里发布更容易。但是,您可以将其复制并粘贴到控制台应用程序中,它应该运行得很好。如果重要的话,我使用的是VS2017,.NET 4.7.1和C#7.2。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static System.Console;
namespace ConsoleApp1
{
class Program
{
public const int MaxNumberOfTasks = 10;
private static readonly Random Random = new Random();
static void Main(string[] args)
{
var workers = new List<IWorker>(MaxNumberOfTasks);
for (var i = 0; i < MaxNumberOfTasks; i++)
workers.Add(GetRandomWorker());
WriteLine("Random Priority Workers\n");
RunWorkersAsync(workers).Wait();
WriteLine("\nSet Priority Workers\n");
RunWorkersByPriorityAsync(workers).Wait();
WriteLine("\nWork Complete\n");
Read();
}
private static async Task RunWorkersAsync(List<IWorker> workers)
{
foreach (var worker in workers)
await worker.DoWork();
}
private static async Task RunWorkersByPriorityAsync(List<IWorker> workers)
{
var highWorkers = new List<IWorker>();
var mediumWorkers = new List<IWorker>();
var lowWorkers = new List<IWorker>();
foreach (var worker in workers)
{
var priorityAttribute = (PriorityAttribute)worker.GetType().GetCustomAttributes(typeof(PriorityAttribute), false).FirstOrDefault();
if (priorityAttribute != null)
{
switch (priorityAttribute.Priority)
{
case Priority.High:
highWorkers.Add(worker);
break;
case Priority.Medium:
mediumWorkers.Add(worker);
break;
case Priority.Low:
default:
lowWorkers.Add(worker);
break;
}
}
else
{
lowWorkers.Add(worker);
}
}
await RunWorkersAsync(highWorkers);
await RunWorkersAsync(mediumWorkers);
await RunWorkersAsync(lowWorkers);
}
private static IWorker GetRandomWorker()
{
var randomNumber = Random.Next(0, 3);
switch (randomNumber)
{
case 0:
return new HighLevelWorker();
case 1:
return new MediumLevelWorker();
case 2:
default:
return new LowLevelWorker();
}
}
}
public interface IWorker
{
Task DoWork();
}
[AttributeUsage(AttributeTargets.Class)]
public class PriorityAttribute : Attribute
{
public PriorityAttribute(Priority priority) => Priority = priority;
public Priority Priority { get; }
}
public enum Priority
{
Low,
Medium,
High
}
[Priority(Priority.High)]
public class HighLevelWorker : IWorker
{
public async Task DoWork()
{
await Task.Delay(200);
WriteLine($"{nameof(HighLevelWorker)} complete.");
}
}
[Priority(Priority.Medium)]
public class MediumLevelWorker : IWorker
{
public async Task DoWork()
{
await Task.Delay(200);
WriteLine($"{nameof(MediumLevelWorker)} complete.");
}
}
[Priority(Priority.Low)]
public class LowLevelWorker : IWorker
{
public async Task DoWork()
{
await Task.Delay(200);
WriteLine($"{nameof(LowLevelWorker)} complete.");
}
}
}
所以有控制台应用程序,这是输出:
Random Priority Workers
MediumLevelWorker complete.
MediumLevelWorker complete.
HighLevelWorker complete.
LowLevelWorker complete.
HighLevelWorker complete.
LowLevelWorker complete.
MediumLevelWorker complete.
MediumLevelWorker complete.
HighLevelWorker complete.
MediumLevelWorker complete.
Set Priority Workers
HighLevelWorker complete.
HighLevelWorker complete.
HighLevelWorker complete.
MediumLevelWorker complete.
MediumLevelWorker complete.
MediumLevelWorker complete.
MediumLevelWorker complete.
MediumLevelWorker complete.
LowLevelWorker complete.
LowLevelWorker complete.
Work Complete
可以从中获取的东西。所有的工人对象完全一样;它们的名称不同,但它们在代码中是相同的,并实现相同的接口;唯一的区别是PriorityAttribute
适用于每个。您可以删除该属性,RunWorkersAsync
和RunWorkerByPriorityAsync
任务都会执行相同的操作。此外,如果您更改任何属性的优先级,您将注意到它,无论该类的名称如何。换句话说,我们可以在有或没有优先级的情况下运行,也可以在需要时修改优先级(尽管在这个例子中,通过命名修改是没有意义的;但这仅仅是出于教育目的。)