У меня есть функция дерева выражений из предыдущего вопроса SO. Это в основном позволяет преобразовать строку данных в определенный класс.Проблема преобразования с деревьями выражений
Этот код отлично работает, если только вы не имеете дело с типами данных, которые могут быть больше или меньше (например, Int32/Int64).
Код генерирует недопустимое исключение литых при переходе от Int64
к Int32
, когда значение будет соответствовать Int32
(например, номера в 3000).
Должен ли я?
- Попытка исправить это в коде? (Если это так, любые указатели?)
Оставьте код таким, как он есть.
private Func<SqlDataReader, T> getExpressionDelegate<T>() { // hang on to row[string] property var indexerProperty = typeof(SqlDataReader).GetProperty("Item", new[] { typeof(string) }); // list of statements in our dynamic method var statements = new List<Expression>(); // store instance for setting of properties ParameterExpression instanceParameter = Expression.Variable(typeof(T)); ParameterExpression sqlDataReaderParameter = Expression.Parameter(typeof(SqlDataReader)); // create and assign new T to variable: var instance = new T(); BinaryExpression createInstance = Expression.Assign(instanceParameter, Expression.New(typeof(T))); statements.Add(createInstance); foreach (var property in typeof(T).GetProperties()) { // instance.MyProperty MemberExpression getProperty = Expression.Property(instanceParameter, property); // row[property] -- NOTE: this assumes column names are the same as PropertyInfo names on T IndexExpression readValue = Expression.MakeIndex(sqlDataReaderParameter, indexerProperty, new[] { Expression.Constant(property.Name) }); // instance.MyProperty = row[property] BinaryExpression assignProperty = Expression.Assign(getProperty, Expression.Convert(readValue, property.PropertyType)); statements.Add(assignProperty); } var returnStatement = instanceParameter; statements.Add(returnStatement); var body = Expression.Block(instanceParameter.Type, new[] { instanceParameter }, statements.ToArray()); var lambda = Expression.Lambda<Func<SqlDataReader, T>>(body, sqlDataReaderParameter); // cache me! return lambda.Compile(); }
Update:
Я теперь отказался и решил, что не стоит. Из приведенных ниже замечаний, я дошел до:
if (readValue.Type != property.PropertyType)
{
BinaryExpression assignProperty = Expression.Assign(getProperty, Expression.Convert(Expression.Call(property.PropertyType, "Parse", null, new Expression[] { Expression.ConvertChecked(readValue, typeof(string)) }), property.PropertyType));
statements.Add(assignProperty);
}
else
{
// instance.MyProperty = row[property]
BinaryExpression assignProperty = Expression.Assign(getProperty, Expression.Convert(readValue, property.PropertyType));
statements.Add(assignProperty);
}
Я не думаю, что я был слишком далеко, не стесняйтесь, чтобы закончить его и отправить ответ, если вы понять это :)
Я не думаю, что вы действительно должны беспокоиться об этом. Если вы хотите использовать эту функцию для интегральных типов, полагайтесь на класс 'System.Convert'. См. [Аналогичный вопрос] (http: // stackoverflow.com/questions/19841120/listt-property-binding-to-dbdatareader-issue? lq = 1) здесь для более гибкого решения lil. – nawfal