分类:
.net后台框架
1.什么是塑形资源
结合http://www.tnblog.net/hb/article/details/2787
对于排序可能要晚点讲解
塑形资源:相当于你去请求一个Api接口时你要请求多少个字段返回给,服务器端就输出多少字段给你
利用的是反射的原理
2.集合塑形资源与单个塑形资源
集合塑形资源EnumerableExtensions.cs
public static class EnumerableExtensions
{
/// <summary>
/// 动态反射集合资源
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <param name="source"></param>
/// <param name="fields"> 指定哪些属性或字段需要进行实例 </param>
/// <returns></returns>
public static IEnumerable<ExpandoObject> ToDynamicIEnumerable<TSource>(this IEnumerable<TSource> source, string fields = null)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
var expandoObjectList = new List<ExpandoObject>();
var propertyInfoList = new List<PropertyInfo>();
if (string.IsNullOrWhiteSpace(fields))
{
//获取类中所有的公共的字段与实例
var propertyInfos = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
//添加到propertyInfoList集合中去
propertyInfoList.AddRange(propertyInfos);
}
else
{
var fieldsAfterSplit = fields.Split(',').ToList();
foreach (var field in fieldsAfterSplit)
{
var propertyName = field.Trim();
if (string.IsNullOrEmpty(propertyName))
{
continue;
}
//获取属性
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)}");
}
//添加到集合中
propertyInfoList.Add(propertyInfo);
}
}
//通过每一个类获取其中的属性,字段的值到List<ExpandoObject> expandoObjectList中
foreach (TSource sourceObject in source)
{
var dataShapedObject = new ExpandoObject();
foreach (var propertyInfo in propertyInfoList)
{
var propertyValue = propertyInfo.GetValue(sourceObject);
((IDictionary<string, object>)dataShapedObject).Add(propertyInfo.Name, propertyValue);
}
expandoObjectList.Add(dataShapedObject);
}
return expandoObjectList;
}
}单个塑形资源ObjectExtensions.cs
public static class ObjectExtensions
{
/// <summary>
/// 动态返回单个资源
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <param name="source"></param>
/// <param name="fields"> 反射所需要的字段(用逗号分隔) </param>
/// <returns></returns>
public static ExpandoObject ToDynamic<TSource>(this TSource source, string fields = null)
{
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(',').ToList();
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($"Can't found property ??{typeof(TSource)}?ˉ on ??{propertyName}?ˉ");
}
var propertyValue = propertyInfo.GetValue(source);
((IDictionary<string, object>)dataShapedObject).Add(propertyInfo.Name, propertyValue);
}
return dataShapedObject;
}
}3.结合我们对前文的PostController.cs的Get方法的修改
[HttpGet(Name = "GetPosts")]
public async Task<IActionResult> Get(PostParameters postParameters)
{
var posts = await _PostRepository.GetAllPosts(postParameters);
var postResources = _mapper.Map<IEnumerable<Post>, IEnumerable<PostResource>>(posts);
#region 塑形资源()
//这里我们是通过Field字段进行查找
var result = postResources.ToDynamicIEnumerable(postParameters.Fields);
#endregion
//判断上一页
var previousPageLink = posts.HasPrevious ? CreatePostUri(postParameters, PaginationResourceUriType.PreviousPage) : null;
//判断下一页
var nextPageLink = posts.HasNext ? CreatePostUri(postParameters, PaginationResourceUriType.NextPage) : null;
var metta = new {
Pagesize = posts.PageSize,
posts.PageIndex,
posts.TotalItemsCount,
posts.PageCount,
PreviousPageLink=previousPageLink,
NextPageLink = nextPageLink
};
//标准化
Response.Headers.Add("x-Pagination", JsonConvert.SerializeObject(metta,new JsonSerializerSettings()
{
//Json输出格式小写
ContractResolver = new CamelCasePropertyNamesContractResolver()
}));
return Ok(result);
}Result:
没塑形之前的

塑形之后(只要id与anthor):

4.问题
问题一:
从上面看出来一个问题,我们发现输出接口的字段首字母变大写了
解决:
Startup.cs-->ConfigureServices方法
services.AddMvc(option =>
{
option.ReturnHttpNotAcceptable = true;
option.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
}).AddJsonOptions(options=> {
//输出小写
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});Result:

问题二:
如果字段不存在那么内部就会异常,所以我们需要进行验证一下
解决:
创建一个ITypeHelperService接口
public interface ITypeHelperService
{
bool TypeHasProperties<T>(string fields);
}创建一个TypeHelperService.cs验证Failed字段并实现ITypeHelperService接口
public class TypeHelperService : ITypeHelperService
{
public bool TypeHasProperties<T>(string fields)
{
if (string.IsNullOrWhiteSpace(fields))
{
return true;
}
var fieldsAfterSplit = fields.Split(',');
foreach (var field in fieldsAfterSplit)
{
var propertyName = field.Trim();
if (string.IsNullOrEmpty(propertyName))
{
continue;
}
var propertyInfo = typeof(T)
.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
{
return false;
}
}
return true;
}
}服务注入
#region 验证塑形字段注册 services.AddTransient<ITypeHelperService, TypeHelperService>(); #endregion
然后再控制器中
[HttpGet(Name = "GetPosts")]
public async Task<IActionResult> Get(PostParameters postParameters)
{
#region 排序验证
if (!_propertyMappingContainer.ValidateMappingExistsFor<PostResource,Post>(postParameters.OrderBy))
{
return BadRequest(" Can't finds fields not sorting ");
}
#endregion
#region 判断塑形字段是否存在
if (!_typeHelperService.TypeHasProperties<PostResource>(postParameters.Fields))
{
return BadRequest("Fields not exist");
}
#endregion
...Result:




欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739
评价
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:
50010702506256
50010702506256
欢迎加群交流技术