Click here to Skip to main content
15,894,319 members
Please Sign up or sign in to vote.
2.00/5 (2 votes)
See more:
Hello,

I am writing an application that uses a static class to store all the apps settings. What I want to do is walk through the properties of the static settings class to display to the user or write to a xml file for retrieval later.

I have used System.ComponentModel.TypeDescriptor.GetProperties(this) to retrieve the properties of an instace of a class before. In MSDN it says that you can use an instance or the type for the parameter to GetProperties. When I use the code below I get null for the PropertyDescriptorCollection. What is wrong with my syntax or approach?

C#
public static String GetProperties()
{
    String sReturn = string.Empty;  // Why have I used s prefix? C# has some variable naming conventions. Why didn't I follow them?
    System.ComponentModel.PropertyDescriptorCollection TypDecs;
    //Settings me = new Settings();
    //me = this;
    try
    {
        // TODO: this returns 0 properties because it is a static class
        //TypDecs = System.ComponentModel.TypeDescriptor.GetProperties(Type.GetType("Settings"));
        //TypDecs = System.ComponentModel.TypeDescriptor.GetProperties(T);
        //TypDecs = System.ComponentModel.TypeDescriptor.GetProperties(this);
        TypDecs = System.ComponentModel.TypeDescriptor.GetProperties(typeof DL_Batch_Import.Settings));
        foreach (System.ComponentModel.PropertyDescriptor Prop in TypDecs)
        {
            sReturn += Prop.DisplayName.ToString() + " = " + Prop.GetValue(Type.GetType("Settings")) + "/n";
        }
    }
    catch (Exception ex)
    {
        // WOW! Empty catch block!
    }
    return sReturn;
}

Thanks,

Michael Z
Posted
Updated 8-Oct-10 9:13am
v3

Does your DL_Batch_Import.Settings type implement IComponent?

Reading the MSDN library article for TypeDescriptor[^] - in particular the Remarks section, it appears that TypeDescriptor is intended for use on classes that implement IComponent: "In contrast [to System.Reflection.Type], TypeDescriptor is an extensible inspection mechanism for components: those classes that implement the IComponent interface." (2nd paragraph).

Perhaps TypeDescriptor requires the types being inspected to implement IComponent? I've not tried it, but it's perhaps a direction to investigate.
 
Share this answer
 
v2
So, since I've not used TypeDescriptor, I'm only guessing ... but I suspect that it won't tell you anything about static properties. From the little I've read, it exists to support people doing COM work, where parts of a type may not be statically known (i.e. known at compile time). But I'm not even sure of that.

The useful thing to infer from 'maybe its related to COM' is that a COM object / interface is related to an instance, so public static anything ... is unlikely to work because the static keyword makes the property (or field) a property of the type, not of an instance of the type.

- Do you need to use TypeDescriptor.GetProperties(), or can you use Type.GetProperties()? If you can use the latter you can discover both instance and static field and/or properties (and methods).

- If you must use TypeDescriptor, can you change your Settings object to be a singleton instance of a type, instead of being the static properties of a static type?

Re VB.Net vs C# - I doubt the problem is due to some intrinsice difference between VB.Net and C#, but to understanding how TypeDesriptor works ... I expect that when you get it to work you'' be able to make it work in both languages. Have you come across Reflector[^]? It's a free reverse-engineering tool for .Net assemblies. It generates C# (or VB.Net) source from the IL in an assembly. So, when you get your problem working in one language, you can use Reflector to see how it would look in the other.

In your 'What I should be doing' section, note that you're declaring myprop as an instance field, but MyProp as a static property: this will not compile because the static property doesn't know anything about the internals of instances.
 
Share this answer
 
I've just re-read you opening description of the problem. Is there a reason why you are not able to use .Net's built-in settings infrastructure?

That infrastructure already reads from / writes to an XML file of settings, and for simple cases you can let the designer in Visual Studio generate the file and Settings class for you (go to the assembly's Properties page, pick the Settings tab and declare the names and types of the settings.

If you need to get more sophisticated than name/value pairs, then perhaps the classes in the System.Configuration namespace will still meet your need.
 
Share this answer
 
Comments
Mzwijacz 11-Oct-10 12:05pm    
There is some behavior that I don't like about the build in configuration. First with the My.Settings the application level settings are read only. The user settings are stored way down in documents and settings someplace and are hard to find.

System.configuration appends a .config to the file name.

Lastly there could be 20 different copies of these settings on how the application is going to be used but the settings are related to each other, so they need to stay togather.

Thats why I went down this path.

Thanks so much for you help Chris,

Michael Z.

BTW I did find that if you do not use a Get/Set both TypeDecriptor and Reflection will not see the properties. It seems to see them as Fields. I was able to discover this because Type.GetFields saw them but Type.GetProperties did not.
Toli,

I don't know what you a talking about ???? ! I'm just trying to find an answer. So far TypeDescriptor.GetProperties has not returned any of the static properties I built. So I'm using Reflection instead. I'll post the code next week.

By the way I don't give a $h*t about reputation points.

Michael Z.
 
Share this answer
 
I ended up using Reflection and did create the properties with get/set,otherwise they are seen as fields.

Thanks for all your help,
Michael Z.

public static Hashtable GetProperties()
        {
            Hashtable htReturn = new Hashtable ();
            try
            {
                Type mytype = Type.GetType("DL_Batch_Import.Settings");
                PropertyInfo[] Props = mytype.GetProperties();
                String sName = String.Empty;
                String sValue = String.Empty;
               //Check Properties
                foreach (PropertyInfo Prop in Props)
                {
                    
                    try
                    {
                        sName = Prop.Name;
                        
                        switch (Prop.PropertyType.Namespace)
                        {
                            case "System.Collections.Generic":
                                foreach (String  Val in (List<String>)Prop.GetValue(null, null))
                                {sValue = sValue + Val + ":";}
                                htReturn.Add(sName, (List<String>)Prop.GetValue(null, null));
                                break;
                            default :
                                sValue = (String)Prop.GetValue(null,null); 
                                htReturn.Add(sName, sValue );
                                break;
                        }
                            
                            Debug.WriteLine("Prop name is " + Prop.Name);
                            Debug.WriteLine("Property Value is " + sValue);
                    }
                    catch (Exception e) { }//Continue to the next item
                }//End for each
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return htReturn;
        }
 
Share this answer
 
I implemented the interface but the properties aren't showing except for Site which is implemented with the Interface.

This leads me to believe that the problem is my understanding of the difference between VB.Net and C#. I think that The way I'm exposing the properties is wrong.

What I'm doing:
public static String myprop = "This is my Property"<br />


What I should be doing:

private String myprop = "This is my Property"<br />
<p><br />
public static String MyProp ()<br />
   {<br />
      get{return myprop}<br />
      set{myprop = value}<br />
   )<br />
</p>


I'm also looking at Type.Getmembers or Type.Getfields

Any other Ideas ?

Thanks,
Michael Z.

 
Share this answer
 
Comments
Toli Cuturicu 8-Oct-10 15:13pm    
Why did you decide to cheat and add a fake answer? Did you really need reputation points so badly?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900