简体   繁体   中英

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

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. 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). 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.

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 .

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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