Можно ли вызвать метод «Set» свойства struct с помощью отражения? - PullRequest
1 голос
/ 08 апреля 2020

Я определяю структуру:

public struct Settable
{
     public string SettableProperty { get; set; }
}

Я могу установить значение свойства структуры обычным способом:

s.SettableProperty = "Abc";

Однако, когда я создаю метод для попытки установите свойство по отражению:

public T CreateWithValue<T>(string propName, string propValue)
{
    var retObj = Activator.CreateInstance<T>();
    var prop = typeof(T).GetProperty(propName);

    var _ = prop.SetMethod.Invoke(retObj, new object[] { propValue});
    return retObj;
}

... и назовите его так:

var x = CreateWithValue<Settable>("SettableProperty", "Abc");

... В итоге SettableProperty инициализируется значением по умолчанию, null. (Никаких исключений не выдается.)

Обратите внимание, что если я определю Settable как class вместо struct , значение будет установлено как ожидается.

Можно ли задать свойства структуры с помощью отражения?

1 Ответ

2 голосов
/ 08 апреля 2020

Проблема здесь в том, что retObj - это T, тип значения, но Invoke принимает object. Это коробок значение, которое создает изолированную копию в куче (внутри коробки), которую вы затем мутируете. Ваша локальная копия в retObj здесь никак не затрагивается, поскольку это полностью отключенная копия значения.

Вместо этого рассмотрим:

public T CreateWithValue<T>(string propName, string propValue)
{
    object retObj = Activator.CreateInstance<T>();
    var prop = typeof(T).GetProperty(propName);

    prop.SetMethod.Invoke(retObj, new object[] { typedValue });
    return (T)retObj;
}

Это создает поле ранее и распаковывает его, чтобы получить измененное значение. Это, однако, не очень эффективно (примечание: я не добавил никакой неэффективности; неэффективность присуща при использовании object API с типом значения). Вы можете убрать ассигнования, если вы счастливы стать намного грязнее.

...