CsvHelper.Configuration.ClassMap<T> 的动态分配属性

问题描述

我想通过动态分配的属性使用 CsvHelper.Configuration.ClassMap

通常您以静态方式映射这样的属性您必须分配每个属性及其“要显示的文本”。

using CsvHelper.Configuration;

        public sealed class CleansqlRowDescriptorMap : ClassMap<CleansqlRowDescriptor>
        {
            public CleansqlRowDescriptorMap()
            {
                Map(f => f.OriginalIndex).Name("Original Index");
                Map(f => f.OriginalRow).Name("Original Row");
            }
       }

我想做以下事情:

using CsvHelper.Configuration;

        public sealed class CleansqlRowDescriptorMap : ClassMap<CleansqlRowDescriptor>
        {
            public CleansqlRowDescriptorMap()
            {
                // Filter by attribute (implementation returns PropertyInfo List)
                List<PropertyInfo> mappedProperties = CleansqlRowDescriptor.Create().FilterPropertiesByAttribute();

                // Dynamically assign each property and its assigned 'attribute value'  
                // At the moment I mapped the PropertyInfo.Name,but I actually need to use the Property as the static example above.  
                // Also need to figure out how to get the Attribute value (displayName in this example).
                mappedProperties.ForEach(prop => Map(f => prop.Name).Name(prop.Name));
            }
       }

我目前在上面使用了以下方法

            [displayName("Original Index")]
            public int OriginalIndex { get; set; }

            [displayName("Original Row")]
            public string OriginalRow { get; set; }

            public string DonotWantToAssignThis { get; set; }

            public List<PropertyInfo> FilterPropertiesByAttribute()
            {
                // This function already returns only the attributes that use
                // [displayName] and other attributes defined for other properties,// ignoring other properties that do not have any of these attributes.

                return properties;
            }

如何使用项目的 PropertyInfo 列表来动态分配 ClassMap?我想用这些属性创建一个基类作为过滤器,所有实现这个基类的类都具有相同的功能,从而更容易“维护映射”。

解决方法

我设法弄明白了,VS Code 没有给我 Map() 函数的所有重载,所以我错过了重载。

这个在所有例子中都使用:

MemberMap<TClass,TMember> Map<TMember>(Expression<Func<TClass,TMember>> expression,bool useExistingMap = true);

我在 JoshClose/CSVHelper 中发现了这个:

public MemberMap Map(Type classType,MemberInfo member,bool useExistingMap = true)

因此,我现在可以直接分配 MemberInfo,而不是使用不采用类型的“需要属性名称为 TMember 的表达式”。

下面的代码仅显示了使用单个属性 [DisplayName] 的 .DisplayName 属性值的解决方案。
对于我目前拥有的其他属性,我需要以不同的方式处理属性值:

mappedProperties.ForEach(prop =>
{
   Map(typeof(CleanSQLRowDescriptor),prop).Name(prop.GetCustomAttribute<DisplayNameAttribute>().DisplayName);
});