【问题标题】:C# NET Looping over object properties stored in ListC# NET 循环遍历存储在 List 中的对象属性
【发布时间】:2018-11-15 17:21:53
【问题描述】:

目前我正在研究涉及将数据导出和导入到 Xlsx 文件的功能。这就是我想要做的:我想要一个可以放在这样的属性之上的属性。

public class MyClass
{
   [XlsxColumn("Column 1")]
   public string myProperty1 { get; set; }
   public int myProperty2 { get; set; }
}

到目前为止,我没有遇到任何问题,但是我想“存储引用”对标有 XlsxColumn 属性的属性。我正在使用反射 将属性数据存储在 List 中

var propsList = MyClass.GetProperties().Where(
   prop => Attribute.IsDefined(prop, typeof(XlsxColumn)));

我有一个列表,其中包含所有用 XlsxColumn 标记的属性(本例中只有 myProperty1)。

编辑:问题是我不知道如何遍历 MyClass 中的属性,而只知道具有 XlsxColumn 属性的属性(因此所有 PropertyInfo 对象都存储在 propsList 变量中),而不是对保存到 Xlsx 文件的每个对象进行反射。

我仅限于 .NET 4.0。

感谢您的宝贵时间。

【问题讨论】:

标签: c# .net excel reflection xlsx


【解决方案1】:

MyClass.GetProperties() 不起作用,因为您必须获取类的类型才能调用GetProperties method。否则,您将调用 MyClass 类中定义的名为 GetProperties 的静态方法。

var propsList = typeof(MyClass).GetProperties().Where(
                prop => prop.IsDefined(typeof(XlsxColumnAttribute), false)).ToList();

如果你只想要名字 (IList<string>):

var propsList = typeof(Excel).GetProperties().Where(
                prop => prop.IsDefined(typeof(XlsxColumnAttribute), false))
                .Select(prop=> prop.Name)
                .ToList();

要使用.Where,您必须包含System.Linq

【讨论】:

    【解决方案2】:

    我必须说我不确定这是否是您正在寻找的解决方案。因为我无法完全弄清楚你的问题是什么。好吧,我已经尽我所能提供了答案。

    我为CachingPropetyProvider 选择了一个静态类,但您可以选择一个实例类并使用依赖注入库并将其用作Singleton。此外,我写了大量的 cmets,所以它尽可能地自我解释。

    让我们定义 MyClass。我也特意改了一点。

    public class MyClass
    {
        [XlsxColumn("Column 1")]
        public string MyProperty1 { get; set; }
    
        [XlsxColumn("Column 2")]
        public int MyProperty2 { get; set; }
    }
    

    我还定义了一个MetaInfo 类来保存缓存的信息。

    public class MetaInfo {
    
        /// <summary>
        /// Immutable class for holding PropertyInfo and XlsxColumn info.
        /// </summary>
        /// <param name="info">PropertyInfo</param>
        /// <param name="attr">XlsxColumn</param>
        public MetaInfo(PropertyInfo info, XlsxColumn attr) {
            PropertyInfo = info;
            Attribute = attr;
        }
    
        /// <summary>
        /// PropertyInfo. You may want to access the value inside the property.
        /// </summary>
        public PropertyInfo PropertyInfo { get; }
    
        /// <summary>
        /// Attribute. You may want to access information hold inside the attribute.
        /// </summary>
        public XlsxColumn Attribute { get; }
    }
    

    最后是主角。这个人负责提供关于类的所有数据

    public class CachingPropProvider {
    
    /// <summary>
    /// Holds the meta information for each type.
    /// </summary>
    private static readonly ConcurrentDictionary<Type, List<MetaInfo>> TypeCache;
    
    /// <summary>
    /// Static constructor is guaranteed to run only once.
    /// </summary>
    static CachingPropProvider() {
        //Initialize the cache.
        TypeCache = new ConcurrentDictionary<Type, List<MetaInfo>>();
    }
    
    /// <summary>
    /// Gets the MetaInfo for the given type. Since We use ConcurrentDictionary it is thread safe.
    /// </summary>
    /// <typeparam name="T">Type parameter</typeparam>
    public static IEnumerable<MetaInfo> GetCachedStuff<T>() {
        //If Type exists in the TypeCache, return the cached value
        return TypeCache.GetOrAdd(typeof(T),Factory);
    }
    
    /// <summary>
    /// Factory method to use to extract MetaInfo when Cache is not hit.
    /// </summary>
    /// <param name="type">Type to extract info from</param>
    /// <returns>A list of MetaInfo. An empty List, if no property has XlsxColumn attrbiute</returns>
    private static List<MetaInfo> Factory(Type @type) {
        //If Type does not exist in the TypeCahce runs Extractor
        //Method to extract metainfo for the given type
        return @type.GetProperties().Aggregate(new List<MetaInfo>(), Extractor);
    }
    
    /// <summary>
    /// Extracts MetaInfo from the given property info then saves it into the list.
    /// </summary>
    /// <param name="seedList">List to save metainfo into</param>
    /// <param name="propertyInfo">PropertyInfo to try to extract info from</param>
    /// <returns>List of MetaInfo</returns>
    private static List<MetaInfo> Extractor(List<MetaInfo> seedList,PropertyInfo propertyInfo) {
        //Gets Attribute
        var customattribute = propertyInfo.GetCustomAttribute<XlsxColumn>();
    
        //If custom attribute is not null, it means it is defined
        if (customattribute != null)
        {
            //Extract then add it into seed list
            seedList.Add(new MetaInfo(propertyInfo, customattribute));
        }
        //Return :)
        return seedList;
    }
    
    }
    

    最后让我们看看如何使用解决方案。其实很简单。

    //Has 2 values inside
    var info = CachingPropProvider.GetCachedStuff<MyClass>();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-20
      • 2014-01-26
      • 1970-01-01
      • 2016-09-09
      • 2016-03-11
      • 2014-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多