Я использую следующий код для создания установщика свойств на основе 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
.