R
Ritmo2k
Guest
I have a requirement to validate an collection of objects against a myriad of constraints before continuing on with subsequent processes. The collection of objects and their relationships define a directed acyclic graph, so instead of re-implementing a model and the associated use cases like topological sort and multiple root detection, I am going to use SD.Tools.Algorithmia.Graphs.
The question I have is with edge design. My edges relate to vertexes through one of two means, only a pointer to the vertex (indicating a default, standard relationship in the processes that follow) or a pointer to a vertex with an additional property holding an integer value.
Seems simple, but when creating a readonly type (the edge), I am struggling at class design which is appealing. My initial thought was two properties that held a less derived type or an interface, then when creating the edge, I could use only one ctor and pass the two objects required to indicate how the vertexes were joined. That is not safe as you can modify the object which the property points to. The next option was to flatten the objects and supply all fields, which results in a gross set of ctors?
Below are examples of the last approach, there has got to be a more eloquent way given the two alternatives for each side of the edge:
public enum KeyTypes
{
DistinguishedName,
Attribute
}
public class DirectoryObjectReportEdge : DirectedEdge<DirectoryObjectReportVertex>
{
private readonly int startDirectorySchemaId;
private readonly int endDirectorySchemaId;
public DirectoryObjectReportEdge(
DirectoryObjectReportVertex startVertex,
DirectoryObjectReportVertex endVertex,
KeyTypes startKeyType,
KeyTypes endKeyType)
: base(startVertex, endVertex)
{
if (KeyTypes.DistinguishedName != startKeyType) { throw new ArgumentException(/*...*/); }
if (KeyTypes.DistinguishedName != endKeyType) { throw new ArgumentException(/*...*/); }
this.StartKeyType = startKeyType;
this.EndKeyType = endKeyType;
}
public DirectoryObjectReportEdge(
DirectoryObjectReportVertex startVertex,
DirectoryObjectReportVertex endVertex,
KeyTypes startKeyType,
int startDirectorySchemaId,
KeyTypes endKeyType)
: base(startVertex, endVertex)
{
if (KeyTypes.Attribute != startKeyType) { throw new ArgumentException(/*...*/); }
if (KeyTypes.DistinguishedName != endKeyType) { throw new ArgumentException(/*...*/); }
this.StartKeyType = startKeyType;
this.startDirectorySchemaId = startDirectorySchemaId;
this.EndKeyType = endKeyType;
}
public DirectoryObjectReportEdge(
DirectoryObjectReportVertex startVertex,
DirectoryObjectReportVertex endVertex,
KeyTypes startKeyType,
KeyTypes endKeyType,
int endDirectorySchemaId)
: base(startVertex, endVertex)
{
if (KeyTypes.DistinguishedName != startKeyType) { throw new ArgumentException(/*...*/); }
if (KeyTypes.Attribute != endKeyType) { throw new ArgumentException(/*...*/); }
this.StartKeyType = startKeyType;
this.EndKeyType = endKeyType;
this.endDirectorySchemaId = endDirectorySchemaId;
}
public DirectoryObjectReportEdge(
DirectoryObjectReportVertex startVertex,
DirectoryObjectReportVertex endVertex,
KeyTypes startKeyType,
int startDirectorySchemaId,
KeyTypes endKeyType,
int endDirectorySchemaId)
: base(startVertex, endVertex)
{
if (KeyTypes.Attribute != startKeyType) { throw new ArgumentException(/*...*/); }
if (KeyTypes.Attribute != endKeyType) { throw new ArgumentException(/*...*/); }
this.StartKeyType = startKeyType;
this.startDirectorySchemaId = startDirectorySchemaId;
this.EndKeyType = endKeyType;
this.endDirectorySchemaId = endDirectorySchemaId;
}
public KeyTypes StartKeyType { get; }
public int StartDirectorySchemaId
{
get
{
if (KeyTypes.Attribute != this.StartKeyType) { throw new InvalidOperationException(/*...*/); }
return this.startDirectorySchemaId;
}
}
public KeyTypes EndKeyType { get; }
public int EndDirectorySchemaId
{
get
{
if (KeyTypes.Attribute != this.EndKeyType) { throw new InvalidOperationException(/*...*/); }
return this.endDirectorySchemaId;
}
}
}
Continue reading...
The question I have is with edge design. My edges relate to vertexes through one of two means, only a pointer to the vertex (indicating a default, standard relationship in the processes that follow) or a pointer to a vertex with an additional property holding an integer value.
Seems simple, but when creating a readonly type (the edge), I am struggling at class design which is appealing. My initial thought was two properties that held a less derived type or an interface, then when creating the edge, I could use only one ctor and pass the two objects required to indicate how the vertexes were joined. That is not safe as you can modify the object which the property points to. The next option was to flatten the objects and supply all fields, which results in a gross set of ctors?
Below are examples of the last approach, there has got to be a more eloquent way given the two alternatives for each side of the edge:
public enum KeyTypes
{
DistinguishedName,
Attribute
}
public class DirectoryObjectReportEdge : DirectedEdge<DirectoryObjectReportVertex>
{
private readonly int startDirectorySchemaId;
private readonly int endDirectorySchemaId;
public DirectoryObjectReportEdge(
DirectoryObjectReportVertex startVertex,
DirectoryObjectReportVertex endVertex,
KeyTypes startKeyType,
KeyTypes endKeyType)
: base(startVertex, endVertex)
{
if (KeyTypes.DistinguishedName != startKeyType) { throw new ArgumentException(/*...*/); }
if (KeyTypes.DistinguishedName != endKeyType) { throw new ArgumentException(/*...*/); }
this.StartKeyType = startKeyType;
this.EndKeyType = endKeyType;
}
public DirectoryObjectReportEdge(
DirectoryObjectReportVertex startVertex,
DirectoryObjectReportVertex endVertex,
KeyTypes startKeyType,
int startDirectorySchemaId,
KeyTypes endKeyType)
: base(startVertex, endVertex)
{
if (KeyTypes.Attribute != startKeyType) { throw new ArgumentException(/*...*/); }
if (KeyTypes.DistinguishedName != endKeyType) { throw new ArgumentException(/*...*/); }
this.StartKeyType = startKeyType;
this.startDirectorySchemaId = startDirectorySchemaId;
this.EndKeyType = endKeyType;
}
public DirectoryObjectReportEdge(
DirectoryObjectReportVertex startVertex,
DirectoryObjectReportVertex endVertex,
KeyTypes startKeyType,
KeyTypes endKeyType,
int endDirectorySchemaId)
: base(startVertex, endVertex)
{
if (KeyTypes.DistinguishedName != startKeyType) { throw new ArgumentException(/*...*/); }
if (KeyTypes.Attribute != endKeyType) { throw new ArgumentException(/*...*/); }
this.StartKeyType = startKeyType;
this.EndKeyType = endKeyType;
this.endDirectorySchemaId = endDirectorySchemaId;
}
public DirectoryObjectReportEdge(
DirectoryObjectReportVertex startVertex,
DirectoryObjectReportVertex endVertex,
KeyTypes startKeyType,
int startDirectorySchemaId,
KeyTypes endKeyType,
int endDirectorySchemaId)
: base(startVertex, endVertex)
{
if (KeyTypes.Attribute != startKeyType) { throw new ArgumentException(/*...*/); }
if (KeyTypes.Attribute != endKeyType) { throw new ArgumentException(/*...*/); }
this.StartKeyType = startKeyType;
this.startDirectorySchemaId = startDirectorySchemaId;
this.EndKeyType = endKeyType;
this.endDirectorySchemaId = endDirectorySchemaId;
}
public KeyTypes StartKeyType { get; }
public int StartDirectorySchemaId
{
get
{
if (KeyTypes.Attribute != this.StartKeyType) { throw new InvalidOperationException(/*...*/); }
return this.startDirectorySchemaId;
}
}
public KeyTypes EndKeyType { get; }
public int EndDirectorySchemaId
{
get
{
if (KeyTypes.Attribute != this.EndKeyType) { throw new InvalidOperationException(/*...*/); }
return this.endDirectorySchemaId;
}
}
}
Continue reading...