简体   繁体   中英

vb.net modifying values of custom attributes in a class

I had an idea to use custom attributes on the properties in a class for databinding purposes in a winforms interface. For example, setting and changing the backcolor, forecolor, and tooltip on a textbox with invalid data. I find that I can bind up the control properties of txtTest for backcolor, etc., to a custom attribute such as BackColorAttr decorating a property in the class such as Name, with no problem. The property value itself is bound to the Text of the textbox, two-way binding of that works just fine, and the initial backcolor, forecolor, etc., are set from the initial values of the custom attributes just the way I had hoped. I'm doing all this through a BindingHelper class that reduces all the coding to a couple of generic methods.

Where I'm stumped is manipulating the values of the custom attributes at a later time. Changing the backcolor to red, for example. Nothing I've tried seems to work. Has anybody tried something like this, or have some guidance as to how I might proceed?

I dont quite follow the first part or what binding has to do with colors or Attributes, but thats not how Attributes work. They are not Property wrappers and Properties , Methods and Types have no idea of the Attributes associated with them (and vice-versa ). They are meta data compiled into the assembly. As such, you cant change the value in any meaningful way.

Test class and test Attribute:

Public Class BarState
    Inherits Attribute

    Public Property State As String

    Public Sub New(t As String)
        State = t
    End Sub
End Class

Public Class Foo

    <BarState("red")>
    Public Property Name As String

End Class

Since State is a property, test if we can set it:

Dim f As New Foo

' get props for the Type
Dim pi As PropertyInfo = f.GetType.GetProperty("Name")

Dim attr = pi.GetCustomAttributes(GetType(BarState), False)

If attr.Length > 0 Then
    ' get prop info for the State property on the Attr Type
    Dim pa As PropertyInfo = attr(0).GetType.GetProperty("State")
    ' change it
    CType(attr(0), BarState).State = "GREEN"
    ' or 
    'pa.SetValue(attr(0), "GREEN", Nothing)

    ' print it  (prints "GREEN" but it does not persist)
    Console.WriteLine(CType(attr(0), BarState).State)
End If

'get the attr again as you might do next time thru
attr = pi.GetCustomAttributes(GetType(BarState), False)
' print the value   (Print "red")
Console.WriteLine(CType(attr(0), BarState).State)

The first print will be "GREEN" but that is only for this instance - it does not persist. The next time you get it, it reverts to "red". Since an Attribute is a Type, we can try to Reflection to change the value using pa.SetValue(attr(0), "GREEN", Nothing) which is commented out. It still wont persist because "red" is compiled into the assembly which is what your starting point will always be.

It might seem like you could keep a Dictionary or collection of the attribute instances for all the properties on all the types. That could work except, they all look alike, so you would have to create a hash to track which Attribute instance goes with what Property on what Type .

And you'd have to keep that collection in sync with the underlying instance objects. The Attribute instance wont know the instance it came from is gone and so the state setting should revert, so your Attribute manager would need to handle that.


You might look into "weavers" which use attributes to tag things (like a value range) then rewrite the assembly to weave in range checks for the tagged properties. Sort of sounds like what you are after I dont know what else they might do along the lines of what you describe.

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