尘叶心繁

.net core 塑形资源

电脑版发表于:2019/10/30 10:53


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.csGet方法的修改

 [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:



关于TNBLOG
TNBLOG,技术分享。技术交流:群号677373950
ICP备案 :渝ICP备18016597号-1
App store Android
精彩评论
{{item.replyName}}
{{item.content}}
{{item.time}}
{{subpj.replyName}}
@{{subpj.beReplyName}}{{subpj.content}}
{{subpj.time}}
猜你喜欢