Как сделать выражение для распаковки? - PullRequest
0 голосов
/ 23 сентября 2019

Я использую следующий код для создания установщика свойств на основе Expression:

Public Function PropertySetExpression(Of TObjectType, TPropertyType)(propertyName As String) As Expression(Of Action(Of TObjectType, TPropertyType))
   Dim paramExpression = Expression.Parameter(GetType(TObjectType), "value")
   Dim propertyExpression = Expression.[Property](paramExpression, propertyName)
   Dim getter = Expression.Lambda(Of Func(Of TObjectType, TPropertyType))(propertyExpression, paramExpression)

   Dim member = CType(getter.Body, MemberExpression)
   Dim param = Expression.Parameter(GetType(TPropertyType), "value")

   Return Expression.Lambda(Of Action(Of TObjectType, TPropertyType))(Expression.Assign(member, param), getter.Parameters(0), param)
End Function

И это прекрасно работает, если во время компиляции указано TProperty.Но иногда мне нужна более гибкая архитектура, и я хочу использовать Object вместо более определенного типа, и этот также отлично работает, если TProperty является ссылочным типом.Но если это тип значения, я получаю эту ошибку:

System.ArgumentException: 'Выражение типа' System.Int32 'нельзя использовать для типа возвращаемого значения' System.Object ''

В ответе на аналогичный вопрос, но о методе получения свойства , Джон Скит объясняет, как это исправить для метода получения свойства, вставляя выражение Convert в поле типа значения для объекта, но я не могу понять, как применить это в обратном направлении к распаковать объект перед установкой обратно в тип значения.

Как я могу это сделать?

Обновление в соответствии с запросом комментария:

Обычный установщик свойства будет выглядеть примерно так:

obj.Id = 3

Приведенный выше код позволяет мне динамически получить функцию для выполнения того же действия.:

Dim setter = PropertySetExpression(Of TMyObject, Integer)("Id").Compile()

...

setter(obj, 3)

Причина для этого может быть в сценариях, где я хочу иметь возможность задавать свойства, указанные, скажем, в текстовом файле, но с высокой производительностью установщика свойств.

Как я сказал вЭлектронная почта, это прекрасно работает.Но иногда я даже не знаю тип данных во время компиляции, поэтому я хочу сделать:

Dim setter = PropertySetExpression(Of TMyObject, Object)(prop_name).Compile()

И позволить установщику иметь дело с боксом / распаковкой из фактического типа данных (Integer вэто дело) до Object.

...