Преобразовать пространство имен объекта и имя в объект - PullRequest
0 голосов
/ 16 апреля 2011

Мне нужно позвонить SetSettings() и, используя 3 элемента в splitSettings, установить EncodeAudio в False.Как бы я поступил так?Преобразовать свойство объекта в чье имя у меня есть в строке.Я понимаю, что могу сделать с оператором switch все мои настройки, но должен быть более динамичный способ сделать это.

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
   }
}

Да, у меня есть экземпляр настроек

Скажите:

Settings settingManager = new Settings();

Я пытаюсь сделать, это динамически установить EncodeAudo в False с использованием элементов splitSettings

settingManager.EncodeAudio = False;

Благодаря помощи TBohnen.jnr я пришел к этому ответу:

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);
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 16 апреля 2011

РЕДАКТИРОВАТЬ Протестировал его с помощью int, bool, double и string, и он сработал, также добавил проверку, чтобы убедиться, что свойство существует, и выдает исключение, которого нет (возможно, нужно изменить исключениевведите)

РЕДАКТИРОВАТЬ 2 : временное решение, добавит больше типов названий к методу конвертации или, если кто-то может предложить более динамичный способ его приведения (если нет, то я предполагаю, что у вас будетзнать все типы, которые будут использоваться)?

EDIT3 Украл метод преобразования из другого вопроса (Крис Тейлор), спасибо: -)

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);

    }

Взято из http://www.haslo.ch/blog/setproperty-and-getproperty-with-c-reflection/

Было бы интересно узнать, работает ли это, создайте быстрый тест:

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();
}

Вывод верен, но не совсем уверен, будет ли он правильно конвертировать все типы.

0 голосов
/ 17 апреля 2011

Как уже упоминали другие, вы должны сделать статический класс SettingsLib статическим. И вам также может понадобиться обработать преобразование значений из строк в целевые типы. Вот простой пример того, как это будет работать.

namespace Service
{
  class Program
  {
    static void Main(string[] args)
    {
      string[] splitSettings = { "SettingsLib.Settings", "EncodeAudio", "False" };
      SetProperty(splitSettings[0], splitSettings[1], splitSettings[2]);  
    }

    static void SetProperty(string typeName, string propertyName, object value)
    {
      var type = Type.GetType(typeName);
      if (type == null) 
      {
        throw new ArgumentException("Unable to get type", "typeName");
      }

      var pi = type.GetProperty(propertyName);
      if (pi == null) 
      {
        throw new ArgumentException("Unable to find property on type", "propertyName");
      }

      object propertyValue = value;

      if (propertyValue != null)
      {
        // You might need more elaborate testing here to ensure that you can handle 
        // all the various types, you might need to special case some types here 
        // but this will work for the basics.
        if (pi.PropertyType != propertyValue.GetType())
        {
          propertyValue = Convert.ChangeType(propertyValue, pi.PropertyType);
        }
      }

      pi.SetValue(null, propertyValue, null);
    }
  }
}

namespace SettingsLib
{
  public static class Settings
  {
    public static bool EncodeAudio { get; set; }    
  }
}
0 голосов
/ 16 апреля 2011

Может быть, вы должны пометить свои устанавливаемые свойства как static, а затем попытаться установить значения с помощью Reflection:

namespace SettingsLib
{
  public static class Settings
  {
    public static bool EncodeAudio { get; set; }
  }
}
namespace Service
{
   void SetSettings()
   {
     string[] splitSettings = { "SettingsLib.Settings", "EncodeAudio", "False" };
     dynamic property = Type.GetType(splitSettings[0]).GetProperty(splitSettings[1]);
     property = splitSettings[2];
   }
}
...