在Asp .net core 中通过属性映射实现动态排序和数据塑形
属性映射服务实现

public class PropertyMappingValue
{
public IEnumerable<string> DestinationProperties { get; private set; }
public PropertyMappingValue(IEnumerable<string> destinationProperties)
{
DestinationProperties = destinationProperties;
}
}
public class PropertyMapping<TSource, TDestination> : IPropertyMapping
{
public Dictionary<string, PropertyMappingValue> _mappingDictionary { get; set; }
public PropertyMapping(Dictionary<string, PropertyMappingValue> mappingDictionary)
{
_mappingDictionary = mappingDictionary;
}
}
public class PropertyMappingService : IPropertyMappingService
{
//PropertyMapping
private Dictionary<string, PropertyMappingValue> _touristRoutePropertyMapping =
new Dictionary<string, PropertyMappingValue>(StringComparer.OrdinalIgnoreCase)
{
{"Id", new PropertyMappingValue(new List<string>(){"Id"}) },
{"Title", new PropertyMappingValue(new List<string>(){"Title"}) },
{"Rating", new PropertyMappingValue(new List<string>(){"Rating"}) },
{"OriginalPrice", new PropertyMappingValue(new List<string>(){"OriginalPrice"})},
};
//PropertyMappings
private IList<IPropertyMapping> _propertyMappings
= new List<IPropertyMapping>();
public PropertyMappingService()
{
_propertyMappings.Add(
new PropertyMapping<TouristRouteDto, TouristRoute> (_touristRoutePropertyMapping)
);
}
//GetPropertyMapping
public Dictionary<string, PropertyMappingValue>
GetPropertyMapping<TSource, TDestination>()
{
var matchingMapping =
_propertyMappings.OfType<PropertyMapping<TSource, TDestination>>();
if (matchingMapping.Count() == 1)
{
return matchingMapping.First()._mappingDictionary;
}
throw new Exception($"Cannot find exact property mapping instance for <{typeof(TSource)}, {typeof(TDestination)}>");
}
//IsMappingExists
public bool IsMappingExists<TSource, TDestination>(string fields)
{
var propertyMapping = GetPropertyMapping<TSource, TDestination>();
if (string.IsNullOrWhiteSpace(fields))
{
return true;
}
var fieldsAfterSplit = fields.Split(",");
foreach (var field in fieldsAfterSplit)
{
var trimmedField = field.Trim();
var indexOfFirstSpace = trimmedField.IndexOf(" ");
var propertyName = indexOfFirstSpace == -1 ?
trimmedField : trimmedField.Remove(indexOfFirstSpace);
if (!propertyMapping.ContainsKey(propertyName))
{
return false;
}
}
return true;
}
//IsPropertiesExists
public bool IsPropertiesExists<T>(string fields)
{
if (string.IsNullOrWhiteSpace(fields))
{
return true;
}
var fieldsAfterSplit = fields.Split(',');
foreach (var field in fieldsAfterSplit)
{
var propertyName = field.Trim();
var propertyInfo = typeof(T)
.GetProperty(
propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance
);
if (propertyInfo == null)
{
return false;
}
}
return true;
}
}
注入服务
动态排序
在Helper中扩展IQueryable封装了ApplySort方法实现动态排序
public static class IQueryableExtensions
{
public static IQueryable<T> ApplySort<T>(
this IQueryable<T> source,
string orderBy,
Dictionary<string, PropertyMappingValue> mappingDictionary
)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (mappingDictionary == null)
{
throw new ArgumentNullException("mappingDictionary");
}
if (string.IsNullOrWhiteSpace(orderBy))
{
return source;
}
var orderByString = string.Empty;
var orderByAfterSplit = orderBy.Split(',');
foreach (var order in orderByAfterSplit)
{
var trimmedOrder = order.Trim();
var orderDescending = trimmedOrder.EndsWith(" desc");
var indexOfFirstSpace = trimmedOrder.IndexOf(" ");
var propertyName = indexOfFirstSpace == -1
? trimmedOrder
: trimmedOrder.Remove(indexOfFirstSpace);
if (!mappingDictionary.ContainsKey(propertyName))
{
throw new ArgumentException($"Key mapping for {propertyName} is missing");
}
var propertyMappingValue = mappingDictionary[propertyName];
if (propertyMappingValue == null)
{
throw new ArgumentNullException("propertyMappingValue");
}
foreach (var destinationProperty in
propertyMappingValue.DestinationProperties)
{
orderByString = orderByString +
(string.IsNullOrWhiteSpace(orderByString) ? string.Empty : ", ")
+ destinationProperty
+ (orderDescending ? " descending" : " ascending");
}
}
return source.OrderBy(orderByString);
}
}
在repository中使用
数据塑形
安装Nuget包
在Helper中封装了IEnumerableExtensions、ObjectExtensions,实现对数据的动态塑形。
public static class IEnumerableExtensions
{
public static IEnumerable<ExpandoObject> ShapeData<TSource>(
this IEnumerable<TSource> source,
string fields
)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
var expandoObjectList = new List<ExpandoObject>();
//避免在列表中遍历数据,创建一个属性信息列表
var propertyInfoList = new List<PropertyInfo>();
if (string.IsNullOrWhiteSpace(fields))
{
// 希望返回动态类型对象ExpandoObject所有的属性
var propertyInfos = typeof(TSource)
.GetProperties(BindingFlags.IgnoreCase
| BindingFlags.Public | BindingFlags.Instance);
propertyInfoList.AddRange(propertyInfos);
}
else
{
//逗号来分隔字段字符串
var fieldsAfterSplit = fields.Split(',');
foreach (var filed in fieldsAfterSplit)
{
// 去掉首尾多余的空格,获得属性名称
var propertyName = filed.Trim();
var propertyInfo = typeof(TSource)
.GetProperty(propertyName, BindingFlags.IgnoreCase
| BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
{
throw new Exception($"属性 {propertyName} 找不到" +
$" {typeof(TSource)}");
}
propertyInfoList.Add(propertyInfo);
}
}
foreach (TSource sourceObject in source)
{
// 创建动态类型对象, 创建数据塑性对象
var dataShapedObject = new ExpandoObject
foreach (var propertyInfo in propertyInfoList)
{
//获得对应属性的真实数据
var propertyValue = propertyInfo.GetValue(sourceObjec
((IDictionary<string, object>)dataShapedObject)
.Add(propertyInfo.Name, propertyValue);
expandoObjectList.Add(dataShapedObject);
}
return expandoObjectList;
}
}
public static class ObjectExtensions
{
public static ExpandoObject ShapeData<TSource>(
this TSource source,
string fields
)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
var dataShapedObject = new ExpandoObject();
if (string.IsNullOrWhiteSpace(fields))
{
var propertyInfos = typeof(TSource)
.GetProperties(BindingFlags.IgnoreCase |
BindingFlags.Public | BindingFlags.Instance);
foreach (var propertyInfo in propertyInfos)
{
var propertyValue = propertyInfo.GetValue(source);
((IDictionary<string, object>)dataShapedObject)
.Add(propertyInfo.Name, propertyValue);
}
return dataShapedObject;
}
var fieldsAfterSplit = fields.Split(',');
foreach (var field in fieldsAfterSplit)
{
var propertyName = field.Trim();
var propertyInfo = typeof(TSource)
.GetProperty(propertyName,
BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
{
throw new Exception($"Property {propertyName} wasn't found " +
$"on {typeof(TSource)}");
}
var propertyValue = propertyInfo.GetValue(source);
((IDictionary<string, object>)dataShapedObject)
.Add(propertyInfo.Name, propertyValue);
}
return dataShapedObject;
}
}
在控制器的Action中使用


在Asp .net core 中通过属性映射实现动态排序和数据塑形的更多相关文章
- ASP.NET Core 中的对象映射之 AutoMapper
目录 AutoMapper 简介 AutoMapper 使用 初始化 Profile设置 扁平化映射 集合映射 投影 条件映射 值转换 设置转换前后行为 配置验证及设置 反向映射 自定义转换器 自定义 ...
- 为什么我的会话状态在ASP.NET Core中不工作了?
原文:Why isn't my session state working in ASP.NET Core? Session state, GDPR, and non-essential cookie ...
- 如何在 ASP.NET Core 中构建轻量级服务
在 ASP.NET Core 中处理 Web 应用程序时,我们可能经常希望构建轻量级服务,也就是没有模板或控制器类的服务. 轻量级服务可以降低资源消耗,而且能够提高性能.我们可以在 Startup 或 ...
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结 1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...
- ASP.NET Core Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射
本章主要简单介绍下在ASP.NET Core中如何使用AutoMapper进行实体映射.在正式进入主题之前我们来看下几个概念: 1.数据库持久化对象PO(Persistent Object):顾名思义 ...
- ASP.NET CORE 中使用AutoMapper进行对象映射
ASP.NET CORE 中使用AutoMapper进行对象映射 1.什么是AutoMapper? AutoMapper是基于对象到对象约定的映射工具,常用于(但并不仅限制于)把复杂的对象模型转为DT ...
- ASP.NET Core中使用IOC三部曲(二.采用Autofac来替换IOC容器,并实现属性注入)
前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...
- ASP.NET Core中使用自定义MVC过滤器属性的依赖注入
除了将自己的中间件添加到ASP.NET MVC Core应用程序管道之外,您还可以使用自定义MVC过滤器属性来控制响应,并有选择地将它们应用于整个控制器或控制器操作. ASP.NET Core中常用的 ...
- ASP.NET Core中如果Response.HasStarted已经为true,就不能更改Response.Cookies和Response.Headers等属性的值了
最近我在ASP.NET Core中做了一个中间件CustomizedMiddleware,要说该中间件的功能也很简单,其实就是往HttpResponse中添加一个Cookie而已,但是我将添加Cook ...
随机推荐
- F5负载均衡_monitors(健康检查)
故障现象: 后端有5台服务器,每个服务器上跑着8个应用.使用F5做应用负载调度.这40个应用里面,3-10个应用在高峰期的时候weblogic的DOS窗口显示与数据库断开连接(端口通.业务断),但是F ...
- Python - 基本数据类型_Number 数字、bool 布尔、complex 复数
Number 数字,是一个大的分类,细分四小类 整数:int 浮点数:float 布尔:bool 复数:complex int 的栗子 print(type(-1)) print(type(1)) p ...
- NOIP 模拟赛 day5 T2 水 故事题解
题目描述 有一块矩形土地被划分成 \(\small n×m\) 个正方形小块.这些小块高低不平,每一小块都有自己的高度.水流可以由任意一块地流向周围四个方向的四块地中,但是不能直接流入对角相连的小块中 ...
- TWAIN.CPP
include "twaincpp.h" #include <QtGlobal> #include <QDateTime> #include <QSt ...
- C语言:变量定义
变量定义:用于为变量分配存储空间,还可为变量指定初始值.程序中,变量有且仅有一个定义.变量声明:用于向程序表明变量的类型和名字.定义也是声明,extern声明不是定义 定义也是声明:当定义变量时我们声 ...
- Java程序设计当堂测试 9.20
/*Java当堂测试 ATM机模拟系统由于学习的知识有限,不能完成所有课上项目,文件的应用没有完成,汇款转账功能也没有写,一些要求该退出的地方也没有写,基本功能还算完善*/ 1 package acc ...
- urllib库中的URL编码解码和GETPOST请求
在urllib库的使用过程中,会在请求发送之前按照发送请求的方式进行编码处理,来使得传递的参数更加的安全,也更加符合模拟浏览器发送请求的形式.这就需要用urllib中的parse模块.parse的使用 ...
- Tomcat网站根目录设置
直接将war放入到webapps目录下 修改server.xml文件,在Host节点下添加如下代码 <Context path="/" docBase="web&q ...
- apt-key Debian packages密钥管理命令
adv子命令 Pass advanced options to gpg. With adv --recv-key you can e.g. download key from keyservers ...
- 在docker for windows建立mssql容器后,ssms连接mssql出现错误号码18456的问题
在docker for windows建立mssql容器后,ssms连接mssql出现错误号码18456的问题 笔者提供一个可能会没考虑到的点. 请检查本机是否安装了mssql!!! 请检查本机的ms ...