С# Reflection - объект не соответствует типу цели

Я пытаюсь использовать метод propertyInfo.SetValue() для установки значения свойства объекта с отражением, и я получаю исключение "Объект не соответствует типу цели". Это не имеет смысла (по крайней мере, для меня!), Поскольку я просто пытаюсь установить простое строковое свойство для объекта со значением замены строки. Вот фрагмент кода - он содержится в рекурсивной функции, поэтому здесь есть еще куча кода, но это мужество:

PropertyInfo fieldPropertyInfo = businessObject.GetType().GetProperties().FirstOrDefault(f => f.Name.ToLower() == piecesLeft[0].ToLower());
businessObject = fieldPropertyInfo.GetValue(businessObject, null);

fieldPropertyInfo.SetValue(businessObject, replacementValue, null);

Я проверил, что businessObject" and replaceValue" имеют одинаковый тип, выполнив это сравнение, которое вернуло true:

businessObject.GetType() == replacementValue.GetType()

Ответ 1

Вы пытаетесь установить значение свойства propertyinfo. Поскольку вы перезаписываете businessObject

PropertyInfo fieldPropertyInfo = businessObject.GetType().GetProperties()
                                 .FirstOrDefault(f => f.Name.ToLower() == piecesLeft[0].ToLower());

// The result should be stored into another variable here:
businessObject = fieldPropertyInfo.GetValue(businessObject, null);

fieldPropertyInfo.SetValue(businessObject, replacementValue, null);

Это должно быть что-то вроде:

PropertyInfo fieldPropertyInfo = businessObject.GetType().GetProperties()
                                 .FirstOrDefault(f => f.Name.ToLower() == piecesLeft[0].ToLower());

// also you should check if the propertyInfo is assigned, because the 
// given property looks like a variable.
if(fieldPropertyInfo == null)
    throw new Exception(string.Format("Property {0} not found", f.Name.ToLower()));

// you are overwriting the original businessObject
var businessObjectPropValue = fieldPropertyInfo.GetValue(businessObject, null);

fieldPropertyInfo.SetValue(businessObject, replacementValue, null);

Ответ 2

Я подозреваю, что вы просто хотите удалить вторую строку. Что он там делает? Вы извлекаете значение свойства из объекта, на которое ссылается businessObject, и устанавливаете его для нового значения businessObject. Поэтому, если это действительно свойство строки, значение businessObject будет потом ссылкой на строку, и вы попытаетесь использовать это как цель для установки свойства! Это немного похоже на это:

dynamic businessObject = ...;
businessObject = businessObject.SomeProperty; // This returns a string, remember!
businessObject.SomeProperty = replacementValue;

Это не сработает.

Неясно, что означает replacementValue - заменить ли строку замены или бизнес-объект реальным значением замены, но я подозреваю, что вы либо хотите:

PropertyInfo fieldPropertyInfo = businessObject.GetType().GetProperties()
      .FirstOrDefault(f => f.Name.ToLower() == piecesLeft[0].ToLower());
fieldPropertyInfo.SetValue(businessObject, replacementValue, null);

Или:

PropertyInfo fieldPropertyInfo = businessObject.GetType().GetProperties()
      .FirstOrDefault(f => f.Name.ToLower() == piecesLeft[0].ToLower());
object newValue = fieldPropertyInfo.GetValue(replacementValue, null);
fieldPropertyInfo.SetValue(businessObject, newValue, null);

Ответ 3

Вы пытаетесь установить значение свойства в businessObject для другого значения типа businessObject, а не типа этого свойства.

Чтобы этот код работал, replacementValue должен быть того же типа, что и поле, определяемое piecesLeft[0], и, очевидно, это не тот тип.