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