简体   繁体   中英

Set property value with reflection

I have class Settings

public class Settings
{
  public string A{get;set;}
  public bool B {get;set;}
  public int C {get;set;}
}

I another class I have property type of Settings

public class VM
{
   public class Settings Settings{get;set;}
}

I want setup values of property Settings with reflection.

I need pass argument type of object to InitializeSettings method.

 public void Init(object viewModel)
    {
        try
        {
            PropertyInfo settings = viewModel.GetType().GetProperty("Settings");

            PropertyInfo[] settingsProperties = settings.PropertyType.GetProperties();

            foreach (PropertyInfo settingsProperty in settingsProperties)
            {
                object value = //load from app.config

                var convertedValue = Convert.ChangeType(value, settingsProperty.PropertyType);

                //how set  value ???
                settingsProperty.SetValue(settings, convertedValue, null);

            }
        }
        catch (Exception exception)
        {
            throw;
        }
    }

This sample code finish with exception

base = {"Object does not match target type."}

I don't know how can I set values on viewModel.Settings properties in Init method?

You don't need to do it that complicated. Once you have extracted the settings object, you can just update that:

PropertyInfo settingsProperty = viewModel.GetType().GetProperty("Settings");
Settings settings = (Settings) settingsProperty.GetValue(viewModel);

settings.A = "Foo";
settings.B = true;
settings.C = 123;

This is already enough to change the settings stored in the view model. If Settings is a value type, you will have to write the changed settings object back to the object, like this:

settingsProperty.SetValue(viewModel, settings);

But that's really all you will have to do. Of course, if you know that viewModel is of type VM , you can just type-cast it, and access the property directly:

Settings settings = ((VM)viewModel).Settings;

So instead of using reflection, a much better way would be to define some base type, or an interface, that has the Settings property and make your view models implement that:

public interface HasSettings
{
    Settings Settings { get; set; }
}

public class VM : HasSettings
{ … }

That way, your method can accept a HasSettings object instead of a plain object , and you can just access the settings object directly:

public void Init (HasSettings viewModel)
{
    viewModel.Settings.A = "Foo bar";
}

If you have different Settings types with different properties, and you want to run reflection on those too, then you can do that as well:

PropertyInfo settingsProperty = viewModel.GetType().GetProperty("Settings");
object settings = settingsProperty.GetValue(viewModel);

for (PropertyInfo prop in settings.GetType().GetProperties())
{
    object value = GetValueForPropertyName(prop.Name); // magic
    prop.SetValue(settings, value);
}

Again, no need to write the settings object back unless it's a value type.

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