Когда я создаю сущности в библиотеке классов, я склоняюсь к добавлению свойства Tag
, которое может использоваться пользователями и расширением библиотек для хранения произвольных данных. с объектом. Теперь я ищу лучший способ реализации такого свойства Tag
в моей библиотеке классов и причины, по которым это происходит.
В System.Windows.Forms Microsoft использует object Tag {get; набор; }
в качестве подписи, но это выглядит слишком ограниченно, поскольку только один может использовать тег в любое время.
Я также подумал о HashTable Tag {get; }
, чтобы позволить кому-либо устанавливать и получать любые данные по ключу, но это кажется слишком «разоблачающим» для библиотеки классов. Тогда IDictionary Tag {get; }
будет лучшим вариантом, но оба позволят любому очистить весь словарь, которого я хочу избежать. Опять же, и HashTable, и IDictionary позволяют работать только с экземплярами объекта
, где что-то общее может быть лучшим выбором. Но Словарь > Tag {get; }
, очевидно, не будет работать для всех возможных потребителей.
Итак, какой путь?
Редактировать: и HashTable, и IDictionary позволяют работать только с экземплярами объекта
, где что-то общее может быть лучшим выбором. Но Словарь > Tag {get; }
, очевидно, не будет работать для всех возможных потребителей.
Итак, какой путь?
Редактировать: и HashTable, и IDictionary позволяют работать только с экземплярами объекта
, где что-то общее может быть лучшим выбором. Но Словарь > Tag {get; }
, очевидно, не будет работать для всех возможных потребителей.
Итак, какой путь?
Редактировать: Как правильно подсказал Тимви ниже, я не хочу, чтобы разные пользовательские классы могли мешать друг другу. Я предполагаю сценарий, в котором есть много классов сущностей и только несколько классов, которые хотят хранить связанные данные.
Похоже, что одно из ваших требований состоит в том, чтобы отдельные потоки или процессы, которые обращаются к объекту сущности, не могли видеть личные данные друг друга. Боюсь, это довольно хороший показатель того, что личные данные не должны находиться в объекте сущности, которым они пользуются. Вместо этого у каждого процесса должны быть свои личные данные.Он не обязательно должен быть в самим объектом сущности, но он может быть связан с объектом сущности через частный словарь:
private Dictionary<Entity, object> myPrivateEntityData = new ...;
Кроме того, поскольку теперь он является частным для процесса, и процесс предположительно точно знает, какие данные он хочет связать с каждой сущностью, теперь вы можете сделать его полностью безопасным для типов.
private Dictionary<Entity, SuperSecretSpecialData> myPrivateEntityData = new ...;
private sealed class SuperSecretData {
public bool NoOne;
public int ElseBut;
public string MeCan;
public DateTime SeeThis;
}
Есть некоторая боль, связанная с необходимостью сначала проверять, есть ли каждая сущность в словаре, но вы тоже можете это исправить. Лично я использую класс AutoDictionary
, который просто расширяет Dictionary
таким образом, что он автоматически создает объекты, когда они отсутствуют:
public sealed class AutoDictionary<TKey, TVal> : Dictionary<TKey, TVal> where TVal : class, new()
{
public new TVal this[TKey key]
{
get
{
if (!ContainsKey(key))
Add(key, new TVal());
return base[key];
}
set
{
base[key] = value;
}
}
}
private AutoDictionary<Entity, SuperSecretSpecialData> myPrivateEntityData = new ...;
Тогда вы можете легко получить доступ к myPrivateEntityData [someEntity ] .NoOne
(и т. Д.), И он будет просто работать и никогда не будет генерировать исключение, потому что ключа нет, и тем не менее вы все равно можете использовать ContainsKey
, если вы хотите , чтобы проверьте, есть ли оно там.
Может быть, что-то вроде этого?
public class Taggable :ITaggable
{
private IDictionary<string, object> _tags = new Dictionary<string, object>();
public void AddTag(string key, object tag)
{
_tags.Add(key,tag);
}
public bool IsTag(string key)
{
return _tags.ContainsKey(key);
}
public T GetTag<T>(string key)
{
return (T) _tags[key];
}
public void RemoveTag(string key)
{
_tags.Remove(key);
}
}
Хотя я не включил это, все четыре метода есть в интерфейсе.
Никто не может «злоупотреблять» коллекцией, так как ему нужно знать ключ.
Вы можете расширить IDictionary
или Dictionary
, чтобы сделать его изменяемым. Однако что-то мне подсказывает, что вы, вероятно, в целом ошибаетесь. Коллекции с произвольной типизацией всегда доставляют удовольствие при доставке ...
Это просто мой 2c, вроде субъективно, но я избегаю свободных типов, если они не нужны.