Шаблон проектирования для глобального кэша объектов с поиском - PullRequest
0 голосов
/ 22 июня 2019

В настоящее время я работаю над проектом, который требует общего интерфейса для определения, совместного использования и поиска иерархии объектов. По сути, это будет общий проект, который определяет общую структуру для всех объектов, и проекты-потребители могут использовать ее для определения объектов и совместного использования их среди других проектов. Мне интересно, существует ли существующий шаблон проектирования, который соответствует этому и реализует это хорошо.

Я уже пытался это сделать, но я не совсем удовлетворен результатами. Мой текущий подход определяет класс Tag, который использует уникальный string в качестве имени, и Guid в качестве идентификатора, генерируемого во время выполнения, для более быстрого поиска (хеширование и приравнивание значений Guid выполняется намного быстрее, чем при работе со строками ). Затем объекты, которые я хочу использовать в глобальных проектах, определяют, что Tag является участником.

В этом текущем проекте объекты Tag служат исключительно в качестве идентификатора и не содержат данных. Я хотел бы изменить дизайн так, чтобы теги содержали данные и служили базовым классом. Однако это становится все более сложным, и поэтому я надеюсь найти установленные шаблоны проектирования или существующие проекты, которые реализуют аналогичную систему для помощи в разработке.

[DebuggerDisplay( "Name = {Name}, Children = {ChildCount}" )]
public class Tag : IDisposable, IEquatable<Tag>
{

  #region Data Members

  public readonly Guid Id;

  public readonly string Name;

  public readonly string FullName;

  public readonly Tag Parent;

  protected readonly HashSet<Tag> children_;

  protected readonly int hash_;

  protected bool isDisposed_;

  #endregion

  #region Properties

  public IReadOnlyCollection<Tag> Children
  {
    [MethodImpl( MethodImplOptions.AggressiveInlining )]
    get => children_;
  }

  public int ChildCount
  {
    [MethodImpl( MethodImplOptions.AggressiveInlining )]
    get => children_.Count;
  }

  public bool HasChildren
  {
    [MethodImpl( MethodImplOptions.AggressiveInlining )]
    get => children_.Count > 0;
  }

  public bool HasParent
  {
    [MethodImpl( MethodImplOptions.AggressiveInlining )]
    get => Parent != null;
  }

  #endregion

  #region Constructor

  public Tag( string name )
    : this( Guid.NewGuid(), name, null )
  {
  }

  public Tag( string name, Tag parent )
    : this( Guid.NewGuid(), name, parent )
  {
  }

  public Tag( Guid id, string name )
    : this( id, name, null )
  {
  }

  public Tag( Guid id, string name, Tag parent )
  {
    Id = id;
    FullName = Name = name;

    children_ = new HashSet<Tag>();
    hash_ = Name.GetHashCode( StringComparison.InvariantCultureIgnoreCase );

    if( parent != null )
    {
      Parent = parent;
      FullName = $"{parent.FullName}.{Name}";
      Parent.AddChild( this );
    }
  }

  ~Tag()
  {
    Dispose( false );
  }

  #endregion

  #region Public Methods

  [MethodImpl( MethodImplOptions.AggressiveInlining )]
  internal void AddChild( Tag child )
  {
    if( !children_.Add( child ) )
    {
      children_.TryGetValue( child, out var existingChild );
      throw new DuplicateTagChildException( this, existingChild, child );
    }
  }

  [MethodImpl( MethodImplOptions.AggressiveInlining )]
  internal void RemoveChild( Tag child )
  {
    children_.Remove( child );
  }

  [MethodImpl( MethodImplOptions.AggressiveInlining )]
  public bool HasChild( Tag child )
  {
    return children_.Contains( child );
  }

  #endregion

  #region Overrides

  [MethodImpl( MethodImplOptions.AggressiveInlining )]
  public bool Equals( Tag other )
  {
    return Name.Equals( other.Name, StringComparison.InvariantCultureIgnoreCase );
  }

  [MethodImpl( MethodImplOptions.AggressiveInlining )]
  public override bool Equals( object obj )
  {
    return obj is Tag other
      && Name.Equals( other.Name, StringComparison.InvariantCultureIgnoreCase );
  }

  [MethodImpl( MethodImplOptions.AggressiveInlining )]
  public override int GetHashCode()
  {
    return hash_;
  }

  #endregion

  #region IDisposable Methods

  public void Dispose()
  {
    Dispose( true );
    GC.SuppressFinalize( this );
  }

  public virtual void Dispose( bool disposing )
  {
    if( isDisposed_ )
      return;

    if( disposing )
    {
    }

    Parent?.RemoveChild( this );
    TagCache.TryRemove( this );

    isDisposed_ = true;
  }

  #endregion

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...