Итак, я пишу парсер, который использует документ xml для создания группы объектов и заполнения их свойств. Я хочу, чтобы пользователь мог с помощью атрибутов поместить свойство, например position.x = "5", а позиция X будет установлена в 5.
Моя проблема в том, что поля типа значения могут быть легко изменены с помощью кода ниже как я могу изменить исходное значение, но свойства типа значения возвращают копию, которая должна быть изменена и переназначена обратно на исходный объект. Любые идеи о том, как обрабатывать свойства типа значения?
Пример: position - это структура типа Vector2, которая является свойством. MyObject.position.x = 5 не будет работать, потому что вызов SetValue для позиции создаст временную позицию и установит для x значение 5. Поэтому фактическая позиция, прикрепленная к объекту, не получит значение 5. Если я сделаю MyObject.position = new Vector2 (5,0), я получу позицию, установленную на 5,0, так как я не пытаюсь изменить позицию элементы и вместо этого присваивать целое значение позиции.
Примечание: я написал несколько методов расширения, чтобы 'GetValue' был действительным для информации об элементе.
private bool SetAttributeValue(string text,object obj,MemberInfo setter)
{
BuildParseMethods();
if (!TryParseAttribute(text, setter.GetMemberType(), out object value))
return false;
setter.SetValue(obj, value);
return true;
}
private void SetChainAttribute(XmlAttribute attribute,object instance)
{
object target = instance;
MemberInfo[] bindings = null;
string[] parts = attribute.Name.Split('.');
Type type = instance.GetType();
for (int i = 0; i < parts.Length; i++)
{
bindings = type.GetMember(parts[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetField | BindingFlags.SetProperty | BindingFlags.IgnoreCase);
if (bindings == null || bindings.Length == 0)
{
Debug.LogError($"Unable to find element {i} of {attribute.Name}");
return;
}
if (i < parts.Length - 1)
{
target = bindings[0].GetValue(target);
type = target != null ? target.GetType() : bindings[0].GetType();
}
}
SetAttributeValue(attribute.Value, target, bindings[0]);
}