Results 1 to 18 of 18

Thread: Reflection, create a class with dynamically named properties

Threaded View

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Reflection, create a class with dynamically named properties

    Hi,

    Strange request here, and before everyone starts shouting "That's not what you should do", let my explain myself first.


    I'm trying to make a very simple audio tag editor. The idea is that the user can select as many audio files as he likes from a ListView, and a PropertyGrid will then display their tags + their values.

    When multiple files are selected, I want the property grid to display the values of the tags that all files have in common, and display empty values for tags that the files do not have in common.

    As an example, look at the properties list in your Visual Studio IDE when you select multiple controls (of the same type for this matter). Select a few Button controls, for example, and notice that the properties whose values are the same (often things like Font, ForeColor, etc) are displayed. Also notice that the values for properties that are not the same (Text, Name, etc) are empty.

    So, suppose the user selects a bunch of files from the same album. The Album entry in my Property Grid should display the name of that album, (and probably the Artist of the album) while the Title entry should be empty (because the songs obviously will have different titles).


    I am reading and writing the tags using the TagLibSharp library which seems to work just fine.

    But here's the catch: I don't want to 'hard-code' which tags my PropertyGrid should display.

    Right now, I am using Reflection to loop through every tag property of every selected file, and I put them in a List(Of List(Of Object)):
    vb.net Code:
    1. Dim allTags = New List(Of List(Of Object))
    2.  
    3. ' Get the type of the Tag property, which contains all tag properties
    4. Dim tagType As Type = tagFiles.First().Tag.GetType()
    5.  
    6. ' Loop through every property in the Tag type
    7. For Each pi As PropertyInfo In tagType.GetProperties()
    8.    Dim list As New List(Of Object)
    9.    
    10.    ' Loop through every file
    11.    For Each file As TagLib.File In tagFiles
    12.       ' add the value of the property represented by "pi" to the list
    13.       list.Add(pi.GetValue(file, Nothing))
    14.    Next
    15.    
    16.    allTags.Add(list)
    17. Next
    (Side-node, the Tag property here is not of type Object as usual in .NET, but it's a class with a property for each tag)

    The code might be a little hard to understand, but basically it loops through every property of the Tag property (things such as Title, Artist, Album, etc) using Reflection. It then loops through every file in the selected files list (tagFiles), and uses Reflection again to get the value of the current Tag property (pi) of the current file. It adds that value to the "list" list, and after every file has been processed, it adds the entire "list" to the "allTags" list.

    So, what I end up with is a list that contains a list of tag values for every file.


    Finally, I want to display one instance of this list (meaning: one instance of a list containing all tag values) in the property grid.

    To be able to display something in the property grid, I need to set the SelectedObject property to an instance of a class. It will then display the properties of that class with their values.

    The obvious problem: there is no class with all the tag values. I can also not create one right now, because I am looping through every tag property dynamically: I don't know which properties it will have!


    So, finally my question: I need to create a class, dynamically, with dynamically named properties (one property for every tag property), and set their values. Even better would be if I could set attributes for those properties (I think the Description attribute controls the way the property is named in the property grid?), but I can't even do the first one...

    How can I generate a class dynamically, probably using Reflection if it's possible at all..?

    In pseudo-.NET code it would probably look something like this
    Code:
    Dim c As New Reflection.DynamicClass("AudioTags")
    c.AddProperty("Title", "Talk")
    c.AddProperty("Album", "X&Y")
    c.AddProperty("Artist", "Coldplay")
    and then, during run-time, it would generate this class
    Code:
    Public Class AudioTags
       
       Public Property Title As String
       Public Property Album As String
       Public Property Artist As String
    
    End Class
    and then create an instance of this, and set its values
    Code:
    Dim tags As New AudioTags()
    tags.Title = "Talk"
    tags.Album = "X&Y"
    tags.Artist = "Coldplay"
    So that I can display and instance of this class in my property grid.

    I think I could do it somehow by generating this code, exactly as I wrote it, in string format, and compiling it on the fly, but I don't really want to unless there is no other option... As far as I know, that method is really slow and very error prone.

    Is there any other way?



    EDIT
    Just to clarify, the reason I need to generate the property names dynamically is of course because I'm showing them in the property grid, so the user will see them. I can't have "property1", "property2", etc, because that's meaningless to the user; it has to be "Title", "Album", etc.

    That's also the reason I would like to use the Description attribute. Many properties have multiple words ("DiscCount" or "BeatsPerMinute") and I would like to display them as "Disc Count" or "Beats per Minute" (or even "BPM") to the user.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width