在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 ...
随机推荐
- 个人博客开发之blog-api项目统一结果集api封装
前言 由于返回json api 格式接口,所以我们需要通过java bean封装一个统一数据返回格式,便于和前端约定交互, 状态码枚举ResultCode package cn.soboys.core ...
- Mongo基于Java基本操作
1.使用Maven依赖相应jar <dependency> <groupId>org.mongodb</groupId> <artifactId>mon ...
- C语言:已知三角形三边长求面积
//已知三角形三边长求面积 #include <stdio.h> #include <math.h> int main() { float a,b,c,p,s; int x=0 ...
- C语言typedef的用法详解
C语言允许为一个数据类型起一个新的别名,就像给人起"绰号"一样. 起别名的目的不是为了提高程序运行效率,而是为了编码方便.例如有一个结构体的名字是 stu,要想定义一个结构体变量就 ...
- CSS 四种样式表 六种规则选择器 五种常用样式属性
新的html程序要在VS中编写了,在vs中安装ASP.NET和Web开发,并用ASP.NET Web 应用程序(.NETFramework)创建一个网页程序.添加一个html页 后面的代码都是在htm ...
- jdk源码阅读-Object类
native 关键字 private static native void registerNatives(); static { registerNatives(); } public final ...
- SSM和Maven整合
项目架构如图 applicationContext.xml还有其他文件一起放进resources下 jsp,js,等文件放在webapp下
- 基于小熊派Hi3861鸿蒙开发的IoT物联网学习【四】
一.互斥锁基本概念: 1.互斥锁又称互斥型信号量,是一种特殊的二值性信号量[二值型信号量可以理解为任务与中断间或者两个任务间的标志,该标志非"满"即"空"],用 ...
- 流暢的python學習-3
一.文件操作 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Thu Apr 23 20:59 ...
- salesforce Integration 概览(一) 杂篇
本篇参考:https://resources.docs.salesforce.com/sfdc/pdf/integration_patterns_and_practices.pdf 我们在做sales ...