Identity
The default implementation is Identity<T>. Identity has following properties: Part, Label and LabelAccessor, Components and IdentityAccessor.
IIdentity identity = new Identity<string>
{
Label = "MyName",
Part = IdentityParts.Name,
Components = null,
LabelAccessor = LabelAccessors.Default.String,
IdentityAccessor = IdentityAccessors.Default.TypeName
};
Parent-property refers to earlier identity node.
// Create namespace part
IIdentity @namespace = new Identity<string>
{
Label = "Namespace",
Part = IdentityParts.Namespace,
};
// Create name part
IIdentity @name = new Identity<string>
{
Label = "Name",
Part = IdentityParts.Name,
Parent = @namespace
};
Static create methods CreateName, CreateNamespace, Create<L> and extension methods AddName, AddNamespace and Add create new node to end of previous.
IIdentity @name = Identities.CreateName("Name").AppendNamespace("Namespace");
LabelAccessor needs to be assigned for equality-comparison, printing-parsing and serialization. There are label accessors in LabelAccessors.
IIdentity<string> identity = new Identity<string>
{
Label = "MyName",
Part = IdentityParts.Name,
LabelAccessor = LabelAccessors.Default.String
};
If label type is not known at compile-time, IdentityBase.Create() can construct identity with a run-time Type reference.
IIdentity name = IdentityBase.Create(typeof(string))
.SetLabelObject("MyName")
.SetLabelAccessor(LabelAccessors.Default.String)
.SetPart(IdentityParts.Name);
Sub-identities are placed into the Components-property.
// Create string identifier
IIdentity @string = Identities.CreateNamespace("System").AppendName("String").SetReadOnly();
// Create Int identifier
IIdentity @int = Identities.CreateNamespace("System").AppendName("Int32").SetReadOnly();
// Create keyvaluepair identifier
IIdentity pair = Identities.CreateNamespace("System").AppendName("KeyValuePair")
.SetComponents(new IIdentity[] { @string, @int })
.SetReadOnly();
Name("KeyValuePair") → Namespace("System") ├── [0] Name("String") → Namespace("System") └── [1] Name("Int32") → Namespace("System")
Immutability
After construction identity is mutable. .SetReadOnly() makes it immutable.
IIdentity name = new Identity<string>()
.SetLabelObject("MyName")
.SetLabelAccessor(LabelAccessors.Default.String)
.SetPart(IdentityParts.Name)
.SetReadOnly();
This extension method requires using of namespace Avalanche.Utilities.
Note
Hashcode is not cached until identity is set read-only. Performance is worse for identities in writable state.
Copying
CloneOrCopy() creates a clone or copy, depending whether the identity implements IIdentityCloneable or not. Clone uses same implementing class as original, copy is instance of Identity<T>.
// Create id
IIdentity id = Identities.CreateNamespace("System").AppendName("String").SetReadOnly();
// Mutate it
IIdentity id2 = id
.CloneOrCopy()
.SetLabelObject("BTree-String");
Name("String") → Namespace("System") Name("BTree-String") → Namespace("System")
Copy() creates a copy as Identity<T>. Copy is in writable state.
// Create id
IIdentity id = Identities.CreateNamespace("System").AppendName("String").SetReadOnly();
// Mutate it
IdentityBase id2 = id.Copy()
.SetLabelObject("BTree-String");
Interface
IIdentity is the interface for identity nodes.
/// <summary>Identity is a linked-list true where each node represent a part of identity.</summary>
public interface IIdentity : IComposition<IIdentity>
{
/// <summary>Link to parent node.</summary>
IIdentity? Parent { get; set; }
/// <summary>
/// Which part of the complete identity this node represents.
/// If <see cref="IdentityParts.None"/> then this identity node does not represent any part of the identity, but carries meta-data.
///
/// See <see cref="IdentityParts"/> for constants for different part types.
/// </summary>
Label8 Part { get; set; }
/// <summary>Reader and writer of this identity type.</summary>
IIdentityAccessor? IdentityAccessor { get; set; }
/// <summary>True node contains a label. If true, then must have <see cref="Part"/> other than <see cref="IdentityParts.None"/>.</summary>
bool HasLabel { get; set; }
/// <summary>The label type of <see cref="IIdentity{L}"/> implementation.</summary>
Type? LabelType { get; set; }
/// <summary>Accessor for reading and writing label value</summary>
ILabelAccessor? LabelAccessor { get; set; }
/// <summary>Label value as object. If label is value-type, reading this value may cause a new box, depending on implementation.</summary>
object? LabelObject { get; set; }
/// <summary>Visit <see cref="ILabelAccessor{T}"/>.</summary>
bool Accept<Visitor>(ref Visitor visitor) where Visitor : IIdentityVisitor;
}
/// <summary>Identity node with specific label type <typeparamref name="L"/></summary>
/// <typeparam name="L">Label type</typeparam>
public interface IIdentity<L> : IIdentity
{
/// <summary>Accessor for reading and writing label value</summary>
new ILabelAccessor<L> LabelAccessor { get; set; }
/// <summary>Label value</summary>
L Label { get; set; }
}
/// <summary>Identity visitor</summary>
public interface IIdentityVisitor
{
/// <summary>Visit <see cref="IIdentityAccessor{L}"/>.</summary>
/// <returns>true to keep visiting, false to stop visitation</returns>
bool Visit<T>(IIdentity<T> identity);
}
Full Example
Full example
using Avalanche.Identity;
using Avalanche.Utilities;
// <05b>
// </05b>
class identity
{
public static void Run()
{
{
// <01>
IIdentity identity = new Identity<string>
{
Label = "MyName",
Part = IdentityParts.Name,
Components = null,
LabelAccessor = LabelAccessors.Default.String,
IdentityAccessor = IdentityAccessors.Default.TypeName
};
// </01>
}
{
// <02>
// Create namespace part
IIdentity @namespace = new Identity<string>
{
Label = "Namespace",
Part = IdentityParts.Namespace,
};
// Create name part
IIdentity @name = new Identity<string>
{
Label = "Name",
Part = IdentityParts.Name,
Parent = @namespace
};
// </02>
}
{
// <02B>
IIdentity @name = Identities.CreateName("Name").AppendNamespace("Namespace");
// </02B>
}
{
// <03>
IIdentity<string> identity = new Identity<string>
{
Label = "MyName",
Part = IdentityParts.Name,
LabelAccessor = LabelAccessors.Default.String
};
// </03>
}
{
// <04>
IIdentity name = IdentityBase.Create(typeof(string))
.SetLabelObject("MyName")
.SetLabelAccessor(LabelAccessors.Default.String)
.SetPart(IdentityParts.Name);
// </04>
}
{
// <05>
IIdentity name = new Identity<string>()
.SetLabelObject("MyName")
.SetLabelAccessor(LabelAccessors.Default.String)
.SetPart(IdentityParts.Name)
.SetReadOnly();
// </05>
}
{
// <06>
// Create string identifier
IIdentity @string = Identities.CreateNamespace("System").AppendName("String").SetReadOnly();
// Create Int identifier
IIdentity @int = Identities.CreateNamespace("System").AppendName("Int32").SetReadOnly();
// Create keyvaluepair identifier
IIdentity pair = Identities.CreateNamespace("System").AppendName("KeyValuePair")
.SetComponents(new IIdentity[] { @string, @int })
.SetReadOnly();
// </06>
}
{
// <07>
// Create id
IIdentity id = Identities.CreateNamespace("System").AppendName("String").SetReadOnly();
// Mutate it
IIdentity id2 = id
.CloneOrCopy()
.SetLabelObject("BTree-String");
// </07>
}
{
// <08>
// Create id
IIdentity id = Identities.CreateNamespace("System").AppendName("String").SetReadOnly();
// Mutate it
IdentityBase id2 = id.Copy()
.SetLabelObject("BTree-String");
// </08>
}
}
}