我如何获得该成员到我的自定义属性应用于? [英] How do I get the member to which my custom attribute was applied?

查看:123
本文介绍了我如何获得该成员到我的自定义属性应用于?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建一个自定义属性在C#和我想要做基于所述属性是否被施加到一个方法对一个属性不同的事情。起初我打算做新的堆栈跟踪()的getFrame(1).GetMethod()在我的自定义属性构造,看看有什么方法调用该属性的构造,但现在我M不能确定,这将使我。如果什么属性应用到的属性?请问实现getMethod()返回该属性的 MethodBase 实例?有没有让到这是在C#应用的属性成员以不同的方式?

  [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property,
    的AllowMultiple = TRUE)]
公共类MyCustomAttribute:属性

更新:好吧,我可能已经问错了问题。从一个自定义属性类中,我怎么成员(或包含成员的类)到我的自定义属性应用于? <一href=\"http://stackoverflow.com/questions/2168942/c-custom-attributes-how-to-get-the-member-type-to-which-an-attribute-was-appl/2169177#2169177\">Aaronaught建议对走堆栈发现,应用了我的属性类的成员,但我怎么回事就从我的属性的构造函数中获取此信息?


解决方案

由于似乎有很多方面的困惑堆栈帧和方法是如何工作的,这里是一个简单的例子:

 静态无效的主要(字串[] args)
{
    MyClass的C =新MyClass的();
    c.Name =MyTest的;
    到Console.ReadLine();
}MyClass类
{
    私人字符串名称;    无效TestMethod的()
    {
        堆栈跟踪ST =新的堆栈跟踪();
        的StackFrame设置currentFrame = st.GetFrame(1);
        MethodBase方法= currentFrame.GetMethod();
        Console.WriteLine(method.Name);
    }    公共字符串名称
    {
        {返回名称; }
        组
        {
            测试方法();
            名称=值;
        }
    }
}

该程序的输出将是:


  

set_Name


在C#属性是语法糖的形式。他们搜集到的IL getter和setter方法​​,这可能是一些.NET语言可能甚至不承认他们是性能 - 性能分辨率按照惯例完全完成,有没有真正在IL规范的规则

现在,让我们说的,你有一个计划,要检查自己的堆栈一个很好的理由的时刻(也有 precious几个的实际理由这样做)。为什么在世界上,你会希望它表现不同的属性和方法?

整个原理背后的属性是它们是一种元数据。如果你想要一个不同的行为,code那么它的到属性的。如果属性可能意味着两种不同的东西取决于它是否是应用于方法或属性 - 那么你应该的两个属性的。设置为 AttributeTargets.Method 上的第一个目标,第二个 AttributeTargets.Property 。简单的。

但再一次,走你自己的堆栈从调用方法拿起一些属性是很危险的最好的。在某种程度上,你是冻结​​你的程序的设计,使之更加困难有人扩展或重构。这不是属性通常使用的方式。更... 相应的的例子,将是这样一个验证属性:

 公共类客户
{
    [需要]
    公共字符串名称{;组; }
}

那么你的验证code,它什么都不知道关于传递在实际的实体,可以这样做:

 公共void验证(对象o)
{
    类型t = o.GetType();
    的foreach(的PropertyInfo在支撑
        t.GetProperties(BindingFlags.Instance | BindingFlags.Public)))
    {
        如果(Attribute.IsDefined(道具的typeof(RequiredAttribute标签))
        {
            对象值= prop.GetValue(0,NULL);
            如果(价值== NULL)
                抛出新RequiredFieldException(prop.Name);
        }
    }
}

在换句话说,你检查的的实例是给你的属性,但你不一定知道的类型什么。 XML属性,数据属性合同,即使属性属性 - 在.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 : Attribute

Update: 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:

set_Name

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 (PropertyInfo 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.

这篇关于我如何获得该成员到我的自定义属性应用于?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆