属性映射服务实现

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 中通过属性映射实现动态排序和数据塑形的更多相关文章

  1. ASP.NET Core 中的对象映射之 AutoMapper

    目录 AutoMapper 简介 AutoMapper 使用 初始化 Profile设置 扁平化映射 集合映射 投影 条件映射 值转换 设置转换前后行为 配置验证及设置 反向映射 自定义转换器 自定义 ...

  2. 为什么我的会话状态在ASP.NET Core中不工作了?

    原文:Why isn't my session state working in ASP.NET Core? Session state, GDPR, and non-essential cookie ...

  3. 如何在 ASP.NET Core 中构建轻量级服务

    在 ASP.NET Core 中处理 Web 应用程序时,我们可能经常希望构建轻量级服务,也就是没有模板或控制器类的服务. 轻量级服务可以降低资源消耗,而且能够提高性能.我们可以在 Startup 或 ...

  4. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  5. ASP.NET Core Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射

    本章主要简单介绍下在ASP.NET Core中如何使用AutoMapper进行实体映射.在正式进入主题之前我们来看下几个概念: 1.数据库持久化对象PO(Persistent Object):顾名思义 ...

  6. ASP.NET CORE 中使用AutoMapper进行对象映射

    ASP.NET CORE 中使用AutoMapper进行对象映射 1.什么是AutoMapper? AutoMapper是基于对象到对象约定的映射工具,常用于(但并不仅限制于)把复杂的对象模型转为DT ...

  7. ASP.NET Core中使用IOC三部曲(二.采用Autofac来替换IOC容器,并实现属性注入)

    前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...

  8. ASP.NET Core中使用自定义MVC过滤器属性的依赖注入

    除了将自己的中间件添加到ASP.NET MVC Core应用程序管道之外,您还可以使用自定义MVC过滤器属性来控制响应,并有选择地将它们应用于整个控制器或控制器操作. ASP.NET Core中常用的 ...

  9. ASP.NET Core中如果Response.HasStarted已经为true,就不能更改Response.Cookies和Response.Headers等属性的值了

    最近我在ASP.NET Core中做了一个中间件CustomizedMiddleware,要说该中间件的功能也很简单,其实就是往HttpResponse中添加一个Cookie而已,但是我将添加Cook ...

随机推荐

  1. 个人博客开发之blog-api项目统一结果集api封装

    前言 由于返回json api 格式接口,所以我们需要通过java bean封装一个统一数据返回格式,便于和前端约定交互, 状态码枚举ResultCode package cn.soboys.core ...

  2. Mongo基于Java基本操作

    1.使用Maven依赖相应jar <dependency> <groupId>org.mongodb</groupId> <artifactId>mon ...

  3. C语言:已知三角形三边长求面积

    //已知三角形三边长求面积 #include <stdio.h> #include <math.h> int main() { float a,b,c,p,s; int x=0 ...

  4. C语言typedef的用法详解

    C语言允许为一个数据类型起一个新的别名,就像给人起"绰号"一样. 起别名的目的不是为了提高程序运行效率,而是为了编码方便.例如有一个结构体的名字是 stu,要想定义一个结构体变量就 ...

  5. CSS 四种样式表 六种规则选择器 五种常用样式属性

    新的html程序要在VS中编写了,在vs中安装ASP.NET和Web开发,并用ASP.NET Web 应用程序(.NETFramework)创建一个网页程序.添加一个html页 后面的代码都是在htm ...

  6. jdk源码阅读-Object类

    native 关键字 private static native void registerNatives(); static { registerNatives(); } public final ...

  7. SSM和Maven整合

    项目架构如图 applicationContext.xml还有其他文件一起放进resources下 jsp,js,等文件放在webapp下

  8. 基于小熊派Hi3861鸿蒙开发的IoT物联网学习【四】

    一.互斥锁基本概念: 1.互斥锁又称互斥型信号量,是一种特殊的二值性信号量[二值型信号量可以理解为任务与中断间或者两个任务间的标志,该标志非"满"即"空"],用 ...

  9. 流暢的python學習-3

    一.文件操作 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Thu Apr 23 20:59 ...

  10. salesforce Integration 概览(一) 杂篇

    本篇参考:https://resources.docs.salesforce.com/sfdc/pdf/integration_patterns_and_practices.pdf 我们在做sales ...