简体   繁体   English

在c#中,是否有可能在不知道包含类的情况下从该属性的实例中获取附加到该属性的属性?

[英]Is it possible in c# to get the attributes attached to a property from within the instance of that property, without knowing the containing class?

The title is a bit of a mouthful, but it's easier to see in code: 标题有点冗长,但是在代码中更容易看到:

public struct MyStruct {
    public bool HasAttribute(Attribute attribute) {
        //is there any way to know?
        return ??????;
    }
}

public class MyClass {
    [SomeAttribute]
    MyStruct child;

    public MyClass() {}
}

I already know how to find the attributes on MyClass.child by getting the property info for each of its properties and then calling GetCustomAttributes , but this only works if I know that the struct instance corresponds to MyClass.child . 我已经知道如何通过获取MyClass.child的每个属性的属性信息,然后调用GetCustomAttributes来查找MyClass.child的属性,但这仅在我知道struct实例对应于MyClass.child情况下才有效。 What I'd like to do here is to figure out if a particular instance of a struct has attributes attached to it, without knowing what class contains the particular instance. 我在这里想要做的是找出某个结构的特定实例是否具有附加的属性,而又不知道哪个类包含该特定实例。

It would make sense to me if you couldn't do this for reference types because the instance could be referenced from multiple places, but shouldn't the set of attributes always be well-defined for value types? 如果您不能为引用类型执行此操作对我来说很有意义,因为可以从多个地方引用该实例,但是难道不应该为值类型始终定义好属性集吗?

My use case is making a library where the behavior of certain objects can be modified slightly by attaching custom attributes. 我的用例是创建一个库,其中可以通过附加自定义属性来稍微修改某些对象的行为。 If there's a more idiomatic way to approach this then I'm open to suggestions. 如果有一种更惯用的方式来处理此问题,那么我愿意提出建议。 I'm also willing to go into an unsafe context if that allows for a solution. 如果允许解决方案,我也愿意进入一个不安全的环境。

Sorry, but that's not possible. 抱歉,那是不可能的。 [SomeAttribute] is attached to the field of MyClass , and is completely unrelated to MyStruct . [SomeAttribute]附加到MyClass字段 ,并且与MyStruct完全无关。

There's no way to get the container of a struct for a couple of reasons: 由于以下几个原因,无法获得结构的容器

  • It could simply be a local variable or a temporary, which means the struct could either live on the stack or in a CPU register. 它可以只是一个局部变量或一个临时变量,这意味着该结构既可以存在于堆栈中,也可以存在于CPU寄存器中。 So, no there's no containing class there. 因此,那里没有包含类。

  • It could be contained in another struct, which would be subject to the same issue. 它可以包含在另一个结构中,该结构也将受到相同的问题。

  • If it's contained in a class, you'd have to retrieve the container type using only the struct's address. 如果它包含在一个类中,则必须仅使用结构的地址来检索容器类型。 And that would involve very nasty code, if possible at all. 如果可能的话,这将涉及非常讨厌的代码。

    Just imagine: The address of such a struct would be the address of its containing class plus an offset. 试想一下:这样的结构的地址就是其包含类的地址加上偏移量。 You'd have to somehow find the address of the container's vtable (assuming you could infer what looks like a vtable just from a memory address). 您必须以某种方式找到容器的vtable的地址(假设您可以仅从内存地址推断出看起来像vtable的地址)。 This would be totally hazardous/unsafe and unreliable, you'd run the risk of getting access violations all the time since you'd have to dereference unknown addresses. 这将是完全危险/不安全不可靠的,因为您必须取消引用未知的地址,所以始终冒着访问冲突的风险。 There's just no way to get something reliable out of it. 只是没有办法从中获得可靠的东西。

    Oh, and you'd also have to do this while the GC could potentially move your container object around, without the possibility of pinning it since you don't know its address in the first place. 哦,您还必须这样做因为GC可能会移动您的容器对象,而不会固定它,因为您首先不知道其地址。

A saner approach would be to use the CLR debugging API, but at this point I'll assume you just don't want to summon Cthulhu . 一个更明智的方法是使用CLR调试API,但在这一点上,我假设您只是不想召唤Cthulhu

I'm sure there are many other ways to achieve what you want there, but I can't be more specific without more details. 我敢肯定还有很多其他方法可以实现您想要的目标,但是如果没有更多细节,我将无法更加具体。 Right now, I'd suggest initializing your struct explicitly, with additional parameters: 现在,建议您使用其他参数显式初始化您的结构:

public class MyClass {
    MyStruct child = new MyStruct(doThatSpecialThingie: true);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM