C#NET遍历列表中存储的对象属性

时间:2018-11-15 17:21:53

标签: c# .net excel reflection xlsx

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

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

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

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

我有一个列表,其中所有属性都标记有XlsxColumn(在此示例中仅是myProperty1)。

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

我仅限于.NET 4.0。

感谢您的时间。

2 个答案:

答案 0 :(得分:0)

我必须说,我不确定这是否是您要寻找的解决方案。因为我不太清楚你的问题是什么。好吧,我已经尽力提供了答案。

我去了CachingPropetyProvider的静态类,但是您可以去实例类,并使用依赖项注入库并将其也用作Singleton。而且,我写了广泛的评论,所以它尽可能自我解释。

让我们定义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>();

答案 1 :(得分:0)

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

相关问题