我有一些int属性,这些属性会多次更新。我希望字典具有随时更新的值,而不是第一个值的0。
class VolleyballMatchSettlementContext2
{
private int _TotalPoints1Set;
private int _TotalPoints2Set;
private int _TotalPoints3Set;
private int _TotalPoints4Set;
private int _TotalPoints5Set;
private readonly Dictionary<int, int> _TotalPointCurrentSet;
public VolleyballMatchSettlementContext2()
{
_TotalPointCurrentSet = new Dictionary<int, int>
{
{1, _TotalPoints1Set},
{2, _TotalPoints2Set},
{3, _TotalPoints3Set},
{4, _TotalPoints4Set},
{5, _TotalPoints5Set}
};
}
}
答案 0 :(得分:0)
如果您不太在意性能。我通过创建一个FieldProxy类来实现此目的,该类使您可以按指定的索引访问字段。代码很大,因为我必须实现整个IDictionary。魔术是通过使用反射来完成的,该反射在性能上并不那么好。
public class FieldProxyDictionary<TK, TV> : IDictionary<TK, TV>
{
private class FieldProxy<T>
{
private readonly Func<T> _getter;
private readonly Action<T> _setter;
public FieldProxy(Func<T> getter, Action<T> setter)
{
_getter = getter;
_setter = setter;
}
public void Set(T value) => _setter(value);
public static implicit operator T(FieldProxy<T> proxy) => proxy._getter();
}
private readonly Dictionary<TK, FieldProxy<TV>> _dictionary = new Dictionary<TK, FieldProxy<TV>>();
public TV this[TK index] {
get => _dictionary[index];
set => _dictionary[index].Set(value);
}
public ICollection<TK> Keys => _dictionary.Keys;
public ICollection<TV> Values => _dictionary.Values.Cast<TV>().ToArray();
public int Count => _dictionary.Count;
public bool IsReadOnly => false;
[Obsolete("Adding items to " + nameof(FieldProxyDictionary<TK, TV>) + " is not supported. Use " + nameof(AddField) + " insted.")]
public void Add(TK key, TV value) => throw new NotSupportedException($"Adding items to {nameof(FieldProxyDictionary<TK, TV>)} is not supported. Use {nameof(AddField)} insted.");
[Obsolete("Adding items to " + nameof(FieldProxyDictionary<TK, TV>) + " is not supported. Use " + nameof(AddField) + " insted.")]
public void Add(KeyValuePair<TK, TV> item) => throw new NotSupportedException($"Adding items to {nameof(FieldProxyDictionary<TK, TV>)} is not supported. Use {nameof(AddField)} insted.");
public void AddField(TK index, object instance, string fieldName)
{
var field = instance.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
TV getter() => (TV)field.GetValue(instance);
void setter(TV value) => field.SetValue(instance, value);
_dictionary[index] = new FieldProxy<TV>(getter, setter);
}
public void Clear() => _dictionary.Clear();
public bool Contains(KeyValuePair<TK, TV> item) => _dictionary.TryGetValue(item.Key, out var value) && ((TV)value).Equals(item.Value);
public bool ContainsKey(TK key) => _dictionary.ContainsKey(key);
public void CopyTo(KeyValuePair<TK, TV>[] array, int arrayIndex) =>
((ICollection<KeyValuePair<TK, FieldProxy<TV>>>)_dictionary)
.Select(proxy => new KeyValuePair<TK, TV>(proxy.Key, proxy.Value))
.ToArray()
.CopyTo(array, arrayIndex);
public IEnumerator<KeyValuePair<TK, TV>> GetEnumerator() => _dictionary.Select(proxy => new KeyValuePair<TK, TV>(proxy.Key, proxy.Value)).GetEnumerator();
public bool Remove(TK key) => _dictionary.Remove(key);
public bool Remove(KeyValuePair<TK, TV> item) => _dictionary.TryGetValue(item.Key, out var value) && ((TV)value).Equals(item.Value) && _dictionary.Remove(item.Key);
public bool TryGetValue(TK key, out TV value)
{
if (_dictionary.TryGetValue(key, out var proxy))
{
value = proxy;
return true;
}
value = default(TV);
return false;
}
IEnumerator IEnumerable.GetEnumerator() => _dictionary.Select(proxy => new KeyValuePair<TK, TV>(proxy.Key, proxy.Value)).GetEnumerator();
}
class VolleyballMatchSettlementContext
{
private int _TotalPoints1Set;
private int _TotalPoints2Set;
private int _TotalPoints3Set;
private int _TotalPoints4Set;
private int _TotalPoints5Set;
public readonly FieldProxyDictionary<int, int> TotalPointCurrentSet;
public VolleyballMatchSettlementContext()
{
TotalPointCurrentSet = new FieldProxyDictionary<int, int>();
TotalPointCurrentSet.AddField(1, this, nameof(_TotalPoints1Set));
TotalPointCurrentSet.AddField(2, this, nameof(_TotalPoints2Set));
TotalPointCurrentSet.AddField(3, this, nameof(_TotalPoints3Set));
TotalPointCurrentSet.AddField(4, this, nameof(_TotalPoints4Set));
TotalPointCurrentSet.AddField(5, this, nameof(_TotalPoints5Set));
}
}
用法是这样的。如果在调试器中检查它,则可以看到这些值存储在上下文实例的字段中。
static class Program
{
static void Main(string[] _)
{
var context = new VolleyballMatchSettlementContext();
context[1] = 1;
context[2] = 2;
context[3] = 3;
context[4] = 4;
context[5] = 5;
Console.WriteLine($"TotalPoints3Set: {context[3]}");
foreach (var field in context.TotalPointCurrentSet)
{
Console.WriteLine($"{field.Key}: {field.Value}");
}
}
}