我目前正在从事一个项目,该项目需要一个用于定义,共享和查找对象层次结构的通用接口。本质上,将存在一个共享项目,该共享项目为所有对象定义了公共结构,而消费项目可以使用它来定义对象并在其他项目之间共享它们。 我想知道是否存在适合这种情况并很好地实现的设计模式。
我已经尝试过了,但是我对结果并不完全满意。我目前的方法定义了一个Tag
类,该类使用唯一的string
作为名称,并使用一个Guid
作为运行时生成的ID,以实现更快的查找(散列和等于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
}