使用反射和表达式的自动列映射
Auto Column Mapping Using Reflection and expression
是否可以通过反射自动执行这些映射?
我有一个简单的列映射:
var columnsMap = new Dictionary<string, Expression<Func<Industry, object>>>
{
["id"] = v => v.Id,
["name"] = v => v.Name,
["isActive"] = v => v.IsActive
};
columnsMap 运行-时间结果:
我想在包装器中自动执行这些映射 class:
public class QueryColumnMapper<T> : Dictionary<string, Expression<Func<T, object>>>
{
public QueryColumnMapper<T> GenerateMappings()
{
foreach (var item in typeof(T).GetProperties())
{
// get dictionary key ======> its OK
var name = Char.ToLowerInvariant(item.Name[0]) + item.Name.Substring(1); //camel-case name
// get expression =======> this is the problem. wrong way
Expression<Func<T, object>> exp = v => v.GetType().GetProperty(item.Name);
//Expression<Func<T, object>> exp = v => v.?????; <-----
// add to mapper object
this.Add(name, exp);
}
return this;
}
}
使用此 class 的示例:
var columnsMap = new QueryColumnMapper<Industry>().GenerateMappings();
columnsMap 运行-时间结果:
我不知道是否可以在 运行 时间内动态获取我的表情?
( 我正在使用此映射字典对实体框架 IQueryable
查询应用过滤。第一个示例(手动映射)可以正常工作,但我不知道如何在 运行-没有手动映射的时间)
您可以使用 属性 名称手动构建自定义表达式
// x =>
var parameter = Expression.Parameter(typeof(T));
// x.Name
var mapProperty = Expression.Property(parameter, "Name");
// (object)x.Name
var convertedExpression = Expression.Convert(mapProperty, typeof(object));
// x => (object)x.Name
var exp = Expression.Lambda<Func<T, object>>(convertedExpression, parameter);
如果这是一个通用子集,并且您发现自己经常这样做,则可以创建一个基本接口。
我为其他观众分享了最终代码:
public class QueryColumnMapper<T>
{
public QueryColumnMapper()
{
Mappings = new Dictionary<string, Expression<Func<T, object>>>();
}
public Dictionary<string, Expression<Func<T, object>>> Mappings { get; set; }
public Dictionary<string, Expression<Func<T, object>>> GenerateMappings()
{
foreach (var item in typeof(T).GetProperties())
{
var name = Char.ToLowerInvariant(item.Name[0]) + item.Name.Substring(1); //camel-case name
// add to mapper object
Mappings.Add(name, GetExpression(item.Name));
}
return Mappings;
}
private Expression<Func<T,object>> GetExpression(string propertyName)
{
// x =>
var parameter = Expression.Parameter(typeof(T));
// x.Name
var mapProperty = Expression.Property(parameter, propertyName);
// (object)x.Name
var convertedExpression = Expression.Convert(mapProperty, typeof(object));
// x => (object)x.Name
return Expression.Lambda<Func<T, object>>(convertedExpression, parameter);
}
}
用法:
var columnsMap = new QueryColumnMapper<Industry>().GenerateMappings();
是否可以通过反射自动执行这些映射?
我有一个简单的列映射:
var columnsMap = new Dictionary<string, Expression<Func<Industry, object>>>
{
["id"] = v => v.Id,
["name"] = v => v.Name,
["isActive"] = v => v.IsActive
};
columnsMap 运行-时间结果:
我想在包装器中自动执行这些映射 class:
public class QueryColumnMapper<T> : Dictionary<string, Expression<Func<T, object>>>
{
public QueryColumnMapper<T> GenerateMappings()
{
foreach (var item in typeof(T).GetProperties())
{
// get dictionary key ======> its OK
var name = Char.ToLowerInvariant(item.Name[0]) + item.Name.Substring(1); //camel-case name
// get expression =======> this is the problem. wrong way
Expression<Func<T, object>> exp = v => v.GetType().GetProperty(item.Name);
//Expression<Func<T, object>> exp = v => v.?????; <-----
// add to mapper object
this.Add(name, exp);
}
return this;
}
}
使用此 class 的示例:
var columnsMap = new QueryColumnMapper<Industry>().GenerateMappings();
columnsMap 运行-时间结果:
我不知道是否可以在 运行 时间内动态获取我的表情?
( 我正在使用此映射字典对实体框架 IQueryable
查询应用过滤。第一个示例(手动映射)可以正常工作,但我不知道如何在 运行-没有手动映射的时间)
您可以使用 属性 名称手动构建自定义表达式
// x =>
var parameter = Expression.Parameter(typeof(T));
// x.Name
var mapProperty = Expression.Property(parameter, "Name");
// (object)x.Name
var convertedExpression = Expression.Convert(mapProperty, typeof(object));
// x => (object)x.Name
var exp = Expression.Lambda<Func<T, object>>(convertedExpression, parameter);
如果这是一个通用子集,并且您发现自己经常这样做,则可以创建一个基本接口。
我为其他观众分享了最终代码:
public class QueryColumnMapper<T>
{
public QueryColumnMapper()
{
Mappings = new Dictionary<string, Expression<Func<T, object>>>();
}
public Dictionary<string, Expression<Func<T, object>>> Mappings { get; set; }
public Dictionary<string, Expression<Func<T, object>>> GenerateMappings()
{
foreach (var item in typeof(T).GetProperties())
{
var name = Char.ToLowerInvariant(item.Name[0]) + item.Name.Substring(1); //camel-case name
// add to mapper object
Mappings.Add(name, GetExpression(item.Name));
}
return Mappings;
}
private Expression<Func<T,object>> GetExpression(string propertyName)
{
// x =>
var parameter = Expression.Parameter(typeof(T));
// x.Name
var mapProperty = Expression.Property(parameter, propertyName);
// (object)x.Name
var convertedExpression = Expression.Convert(mapProperty, typeof(object));
// x => (object)x.Name
return Expression.Lambda<Func<T, object>>(convertedExpression, parameter);
}
}
用法:
var columnsMap = new QueryColumnMapper<Industry>().GenerateMappings();