Search code examples
c#reflectionc#-4.0reference-type

Convert object namespace and name to object


I need to call SetSettings() and using the 3 elements in splitSettings, set EncodeAudio to False. How would I go about doing that? Convert the property of a object to who's name I have in a string. I realize I could do with with a switch statement of all my settings but there has to be a more dynamic way to go about doing this.

namespace SettingsLib
{
  public class Settings
  {
    public Boolean EncodeAudio { get; set; }
  }
}
namespace Service
{
   void SetSettings()
   {
     string[] splitSettings = { "SettingsLib.Settings", "EncodeAudio", "False" };
     // Need to set EncodeAudio to False in SettingsLib.Settings
   }
}

Yes I have a instance of Settings

Say:

Settings settingManager = new Settings();

I am trying to do is dynamically set EncodeAudo to False by using elements of splitSettings

settingManager.EncodeAudio = False;

Thanks to the help of TBohnen.jnr I came to this answer:

public void setProperty(object containingObject, string propertyName, object newValue)
{
    foreach (PropertyInfo p in containingObject.GetType().GetProperties())
    {
        if (p.Name == propertyName)
        {
            p.SetValue(containingObject, Convert.ChangeType(newValue, p.PropertyType), null);
        }
    }
}

Solution

  • EDIT Tested it with int, bool, double and string and it worked, also added a check to make sure that the property exists and throws an exception of it doesn't (Might want to change Exception type)

    EDIT 2: Temporary solution, will add more typenames to the convert method or alternatively if somebody can suggest a more dynamic way of casting it (If not then I assume you will have to know all of the types that will be used)?

    EDIT3 Stole the convert method from another answer in question (Chris Taylor ), thanks :-)

    public void setProperty(object containingObject, string propertyName, object newValue)
        {
            if (containingObject.GetType().GetProperties().Count(c => c.Name == propertyName) > 0)
            {
                var type = containingObject.GetType().GetProperties().First(c => c.Name == propertyName).PropertyType;
                object val = Convert(type,(string)newValue);
                containingObject.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, containingObject, new object[] { val });
            }
            else
            {
                throw new KeyNotFoundException("The property: " + propertyName + " was not found in: " + containingObject.GetType().Name);
            }
        }
    
        public object convert(System.Type type, string value)
        {
            return Convert.ChangeType(value, type);
    
        }
    

    Taken from http://www.haslo.ch/blog/setproperty-and-getproperty-with-c-reflection/

    Was interested to see if this works, create a quick test:

    class testSettings
    {
        public bool SetBool { get; set; }
    
        public void setProperty(object containingObject, string propertyName, object newValue) 
        {
             if (containingObject.GetType().GetProperties().Count(c => c.Name == propertyName) > 0)
            {
                containingObject.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, containingObject, new object[] { newValue });
            }
            else
            {
                throw new KeyNotFoundException("The property: " + propertyName + " was not found in: " + containingObject.GetType().Name);
            }
        }
    }
    
    static void Main(string[] args)
    {
        testSettings ts = new testSettings();
        ts.SetBool = false;
        ts.setProperty(ts, "SetBool", true);
        Console.WriteLine(ts.SetBool.ToString());
        Console.Read();
    }
    

    The output is true, not entirely sure if it will convert all types correctly though.