处理不同的数据集
本文关键字:数据集 处理 | 更新日期: 2023-09-27 18:21:34
我在编写代码时遇到了设计/架构问题。例如,现在我将数据存储在:中
internal interface IProperty<TKey1, TKey2> : IDictionary<TKey1, TKey2> { }
internal class PropertyDictionary<TKey1, TKey2> : IProperty<TKey1, TKey2>
我在PropertyDictionary中实现了IDictionary。还有PropertyDictionary,我可以有一个键,然后为该值创建一个具有公共属性的不可变对象。然后我可以通过以下方式轻松地引用数据:
foreach (var data in inputData.Values)
{
var propertyValue = data.MyDataProperty;
}
首先,这种方式存储数据似乎有很多开销,但现在更重要的是,当我需要扩展PropertyDictionary的功能(例如,将RetrievePrice包括在内)时,它变得很复杂,因为我需要在接口中添加额外的方法,然后按如下方式创建一个新类:
internal interface IAssetPriceData<in TKey1>
{
double RetrievePrice(TKey1 key);
}
internal class PriceDictionary<TKey1, TKey2> : PropertyDictionary<TKey1, TKey2>, IAssetPriceData<TKey1>
因此,我应该如何构建代码以轻松存储不同类型的数据,然后轻松检索这些数据,这样我就可以对存储的属性进行操作/执行计算。
对于任何感兴趣的人,我写了一个类似于这里描述过的类(如下)。我为一些WPF绑定场景对相同类型的属性进行了分组,并绑定到字典元素。我不想使用字典,因为框架会引发(并吃掉)未找到关键字的异常。这一个将字典包装起来,并将字符串硬编码为键,尽管它可能会被泛化以适应这里描述的目的。需要注意的主要事项是索引器在找不到键时的行为——它返回默认的T,而不是抛出异常。
///这个类表示用于绑定的通用集合///哈希项从不为null,Indexer从不抛出异常,在缓存未命中时返回默认值公共类BindableHash:IEnumerable{#区域字段
/// <summary>Current implementation of the hash is a dictionary</summary>
private readonly Dictionary<string, T> _HashItems = new Dictionary<string, T>();
#endregion
#region Properties
/// <summary>How many items are currently in the hash</summary>
public virtual int Count { get { return _HashItems.Count; } }
/// <summary>Indexer provides hashed (by string) lookup</summary>
public virtual T this[string index]
{
get { return index != null && _HashItems.ContainsKey(index) ? _HashItems[index] : default(T); }
}
#endregion
#region Constructors
/// <summary>Default constructor initializes hash with no members</summary>
public BindableHash() : this(null) { }
/// <summary>Injected constructor seeds the list using the tuples passsed in</summary>
public BindableHash(params Tuple<string, T>[] initialTuples)
{
foreach (Tuple<string, T> tuple in initialTuples ?? new Tuple<string, T>[] { })
{
Add(tuple);
}
}
#endregion
#region Methods
/// <summary>Add a key-value pair to the hash</summary>
public virtual void Add(string key, T value)
{
Add(new Tuple<string, T>(key, value));
}
/// <summary>Removes all items from the hash</summary>
public virtual void Clear()
{
_HashItems.Clear();
}
/// <summary>Remove a particular value from the hash</summary>
public bool Remove(string key)
{
return key != null && _HashItems.Remove(key);
}
#endregion
#region Helpers
/// <summary>Abstraction for adding a key value pair</summary>
protected void Add(Tuple<string, T> tuple)
{
if (tuple != null && tuple.Item1 != null)
{
_HashItems[tuple.Item1] = tuple.Item2;
}
}
#endregion
#region IEnumerable<T> Members
/// <summary>Define enumerator retrieval to allow enumeration over values</summary>
public IEnumerator<T> GetEnumerator()
{
foreach (T value in _HashItems.Values)
{
yield return value;
}
}
#endregion
#region IEnumerable Members
/// <summary>Impelementation for clients who cast this as non-generic IEnumerable</summary>
/// <remarks>If you're not familiar with the black magic going on here, IEnmerable generic interface inherits from
/// IEnumerable non-generic (legacy). Both interfaces define GetEnumerator, and one returns a generic IEnumerator and the other
/// a non-generic IEnumerator. This one is the non-generic, and we want to 'hide' it for type safety purposes. When you
/// do an explicit interface implementation, you create some kind of visibility purgatory. This method is not private/protected
/// because the interface is public, but it is also not a public method of this class. The only way you can get to this guy is by casting
/// BindableHash as IEnumerable (non-generic) and invoking the method that way. Since that is possible to do, we have to implement the method,
/// which we do by just invoking our generic one. This is legal because of the fact that IEnumerator generic inherits from non-generic IEnumerator.
/// Clear as mud? You can ask me for a more detailed explanation, if you like --ebd</remarks>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}