Abp.DataDictionary icon indicating copy to clipboard operation
Abp.DataDictionary copied to clipboard

能否支持自动渲染复杂对象

Open YaoaY opened this issue 3 years ago • 0 comments

很常见地,数据对象会有一些非简单类型的成员、列表等也可能含有需要渲染的字典字段。 以目前的方式,只能逐个去手动处理,在试着手动渲染了几处之后,发现非常的麻烦且冗余。

希望能加上自动渲染复杂对象的功能。

我尝试自己扩展,临时实现了一下,方式可能不是太好,供参考。

加了一个特性:DictionaryChildFieldAttribute,用来标记需要进一步渲染的字段。

扩展了DataDictionaryLoaderScanRules方法: 把标记了DictionaryChildField的字段记录下来,并且判断一下是否是IEnumerable,也记录下来 这里借用了 DataDictionaryRule ,临时用自己的方式保存了规则信息

               var properties = type
                    .GetProperties()
                    .Where(p => p.IsDefined(typeof(DictionaryChildFieldAttribute)))
                    .ToList();

                rules.AddRange(properties.Select(property => new DataDictionaryRule
                {
                    DictionaryCode = property.PropertyType.IsAssignableTo(typeof(IEnumerable)) ? "IEnumerable" : "",
                    DtoType = type, 
                    RenderFieldProperty = property, 
                    DictionaryCodeProperty = null
                }));

在需要的字段加上这个特性作为标记:

public class PlanDto {

        [DictionaryCodeField(“Category")]
        public string Category { get; set; }

        [DictionaryRenderField(“Category")]
        public string CategoryName { get; set; }

        [DictionaryChildField] 
        public List<TeamDto> Teams {get;set;}
 
        [DictionaryChildField]
        public User Manager {get;set;}
}

扩展了一个非泛型的Render方法,将 Type 作为参数传入: Task RenderAsync(object sourceDto, Type dtoType)

渲染时,增加了对”新规则“的处理:

               if (rule.DictionaryCodeProperty == null)
                {
                    var childDto = rule.RenderFieldProperty.GetValue(sourceDto);
                    if (rule.DictionaryCode == "IEnumerable" && childDto != null)
                    {
                        var type = rule.RenderFieldProperty.PropertyType.GenericTypeArguments.FirstOrDefault();
                        foreach (var item in (IEnumerable) childDto)
                        {
                            await RenderAsync(item, type);
                        }
                    }
                    else
                    {
                        await RenderAsync(childDto, rule.RenderFieldProperty.PropertyType);    
                    }
                    
                    continue;
                }

目前使用暂无问题,但还是希望用上原生功能

YaoaY avatar Jul 24 '21 04:07 YaoaY