现在,让我们暂时假设您有一个非常好的理由让程序想要检查自己的堆栈(并且这样做有极少的实际理由).为什么您希望它在属性和方法方面表现不同?属性背后的全部原理是它们是一种元数据.如果您想要不同的行为,请将其编码到属性中.如果一个属性可以根据它是应用于方法还是属性而意味着两个不同的东西——那么你应该有两个属性.将第一个目标设置为 AttributeTargets.Method,将第二个目标设置为 AttributeTargets.Property.简单.但是再一次,遍历自己的堆栈以从调用方法中获取一些属性充其量是危险的.在某种程度上,您正在冻结程序的设计,使任何人都难以扩展或重构.这不是通常使用属性的方式.一个更合适的示例,类似于验证属性:公共类客户{[必需的]公共字符串名称 { 获取;放;}}然后您的验证器代码(它对传入的实际实体一无所知)可以执行以下操作:public void Validate(object o){输入 t = o.GetType();foreach (var prop int.GetProperties(BindingFlags.Instance | BindingFlags.Public)){if (Attribute.IsDefined(prop, typeof(RequiredAttribute))){对象值 = prop.GetValue(o, null);如果(值 == 空)抛出新的RequiredFieldException(prop.Name);}}}换句话说,您正在检查提供给您的实例的属性,但您不一定知道它的类型.XML 属性、数据协定属性,甚至 Attribute 属性 - .NET Framework 中的几乎所有属性都以这种方式使用,以实现一些相对于实例类型而动态的功能,而不是动态的到程序的状态或堆栈中发生的事情.在您创建堆栈跟踪时,您实际上不太可能控制它.因此,我将再次建议您不要使用堆栈遍历方法,除非您有充分的理由这样做而您还没有告诉我们.否则你很可能会发现自己身处一个受伤的世界.如果你绝对必须(不要说我们没有警告你),那么使用两个属性,一个可以应用于方法,一个可以应用于属性.我想你会发现它比单个超级属性更容易使用.I'm creating a custom attribute in C# and I want to do different things based on whether the attribute is applied to a method versus a property. At first I was going to do new StackTrace().GetFrame(1).GetMethod() in my custom attribute constructor to see what method called the attribute constructor, but now I'm unsure what that will give me. What if the attribute was applied to a property? Would GetMethod() return a MethodBase instance for that property? Is there a different way of getting the member to which an attribute was applied in C#?[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]public class MyCustomAttribute : AttributeUpdate: okay, I might have been asking the wrong question. From within a custom attribute class, how do I get the member (or the class containing the member) to which my custom attribute was applied? Aaronaught suggested against walking up the stack to find the class member to which my attribute was applied, but how else would I get this information from within the constructor of my attribute? 解决方案 Since there seems to be a lot of confusion with respect to how the stack frames and methods work, here is a simple demonstration:static void Main(string[] args){ MyClass c = new MyClass(); c.Name = "MyTest"; Console.ReadLine();}class MyClass{ private string name; void TestMethod() { StackTrace st = new StackTrace(); StackFrame currentFrame = st.GetFrame(1); MethodBase method = currentFrame.GetMethod(); Console.WriteLine(method.Name); } public string Name { get { return name; } set { TestMethod(); name = value; } }}The output of this program will be:Properties in C# are a form of syntactic sugar. They compile down to getter and setter methods in the IL, and it's possible that some .NET languages might not even recognize them as properties - property resolution is done entirely by convention, there aren't really any rules in the IL spec.Now, let's say for the moment that you had a really good reason for a program to want to examine its own stack (and there are precious few practical reasons to do so). Why in the world would you want it to behave differently for properties and methods?The whole rationale behind attributes is that they are a kind of metadata. If you want a different behaviour, code it into the attribute. If an attribute can mean two different things depending on whether it's applied to a method or property - then you should have two attributes. Set the target on the first to AttributeTargets.Method and the second to AttributeTargets.Property. Simple.But once again, walking your own stack to pick up some attributes from the calling method is dangerous at best. In a way, you are freezing your program's design, making it far more difficult for anybody to extend or refactor. This is not the way attributes are normally used. A more appropriate example, would be something like a validation attribute:public class Customer{ [Required] public string Name { get; set; }}Then your validator code, which knows nothing about the actual entity being passed in, can do this:public void Validate(object o){ Type t = o.GetType(); foreach (var prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (Attribute.IsDefined(prop, typeof(RequiredAttribute))) { object value = prop.GetValue(o, null); if (value == null) throw new RequiredFieldException(prop.Name); } }}In other words, you're examining the attributes of an instance that was given to you but which you don't necessarily know anything about the type of. XML attributes, Data Contract attributes, even Attribute attributes - almost all attributes in the .NET Framework are used this way, to implement some functionality that is dynamic with respect to the type of an instance but not with respect to the state of the program or what happens to be on the stack. It is very unlikely that you are actually in control of this at the point where you create the stack trace.So I'm going to recommend again that you don't use the stack-walking approach unless you have an extremely good reason to do so which you haven't told us about yet. Otherwise you are likely to find yourself in a world of hurt.If you absolutely must (don't say we didn't warn you), then use two attributes, one that can apply to methods and one that can apply to properties. I think you'll find that to be much easier to work with than a single super-attribute. 这篇关于如何获取应用了我的自定义属性的成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-05 09:06