Xafari framework provides a number of features for a comfortable and efficient work with hierarchical data. These features are available for objects that implement IHierarchyNode interface.
This post describes several ways to obtain hierarchical business objects:
Implement IHierarchyNode interface from scratch, the result is XPO
publicclass HierarchyNodeObject : BaseObject, Xafari.Base.IHierarchyNode{public HierarchyNodeObject(Sessionsession): base(session){}//HierarchyNodeNamePropertyAttribute used in HierarchyNodePersistentHelper[HierarchyNodeNameProperty()]publicString Name {get;set;}//PrentPropertyAttribute describe Parent property. You need to set it.[Association("Parent - Children")][ParentProperty()]public HierarchyNodeObject Parent {get;set;}[Association("Parent - Children")]//ChilderPropertyAttribute is obligitory[ChildrenProperty()]public XPCollection Children {get{ return GetCollection("Children");}}
#region Implementation of IHierarchyNode
publicstring GetHierarchyNodeName(string hierarchyName =null){
return HierarchyNodePersistentHelper.GetNodeName(this, hierarchyName);}publicstring GetHierarchyNodeFullName(string hierarchyName =null){
return HierarchyNodePersistentHelper.GetNodeFullName(this, hierarchyName);}public void SetHierarchyNodeFullName(string value, string hierarchyName =null){
HierarchyNodePersistentHelper.SetNodeFullName(this, value, hierarchyName);}publicstring GetHierarchyNodeFullPath(string hierarchyName =null){
return HierarchyNodePersistentHelper.GetNodeFullPath(this, hierarchyName);}public void SetHierarchyNodeFullPath(string value, string hierarchyName =null){
HierarchyNodePersistentHelper.SetNodeFullPath(this, value, hierarchyName);}public Xafari.Base.IHierarchyNode GetHierarchyParent(string hierarchyName =null){
return HierarchyNodePersistentHelper.GetParent(this, hierarchyName);}public void SetHierarchyParent(Xafari.Base.IHierarchyNode parent, string hierarchyName =null){
HierarchyNodePersistentHelper.SetParent(this, parent, hierarchyName);}public IList GetHierarchyChildren(string hierarchyName =null){
return HierarchyNodePersistentHelper.GetChildren(this, hierarchyName);}
#endregion
}
public class HierarchyNodeObject : BaseObject, Xafari.Base.IHierarchyNode
{
public HierarchyNodeObject(Session session) : base(session) { }//HierarchyNodeNamePropertyAttribute used in HierarchyNodePersistentHelper
[HierarchyNodeNameProperty()]
public String Name { get; set; }//PrentPropertyAttribute describe Parent property. You need to set it.
[Association("Parent - Children")]
[ParentProperty()]
public HierarchyNodeObject Parent { get; set; }[Association("Parent - Children")]
//ChilderPropertyAttribute is obligitory
[ChildrenProperty()]
public XPCollection Children { get { return GetCollection("Children"); } }#region Implementation of IHierarchyNodepublic string GetHierarchyNodeName(string hierarchyName = null)
{
return HierarchyNodePersistentHelper.GetNodeName(this, hierarchyName);
}public string GetHierarchyNodeFullName(string hierarchyName = null)
{
return HierarchyNodePersistentHelper.GetNodeFullName(this, hierarchyName);
}
public void SetHierarchyNodeFullName(string value, string hierarchyName = null)
{
HierarchyNodePersistentHelper.SetNodeFullName(this, value, hierarchyName);
}
public string GetHierarchyNodeFullPath(string hierarchyName = null)
{
return HierarchyNodePersistentHelper.GetNodeFullPath(this, hierarchyName);
}
public void SetHierarchyNodeFullPath(string value, string hierarchyName = null)
{
HierarchyNodePersistentHelper.SetNodeFullPath(this, value, hierarchyName);
}public Xafari.Base.IHierarchyNode GetHierarchyParent(string hierarchyName = null)
{
return HierarchyNodePersistentHelper.GetParent(this, hierarchyName);
}public void SetHierarchyParent(Xafari.Base.IHierarchyNode parent, string hierarchyName = null)
{
HierarchyNodePersistentHelper.SetParent(this, parent, hierarchyName);
}
public IList GetHierarchyChildren(string hierarchyName = null)
{
return HierarchyNodePersistentHelper.GetChildren(this, hierarchyName);
}
#endregion
}
As you can see from the code snippet above, HierarchyNodePersistentHelper class provides a ready-to-use method, thus allowing to implement IHierarchyNode interface very quickly and easily. Of course, if necessary, you can encode the methods of the interface on your own.
When implementing IHierarchyNode you must also declare Name, Parent and Children properties and decorate these with appropriate attributes: HierarchyNodeNamePropertyAttribute, ParentPropertyAtribute and ChildrenPropertyAttribute.
2. HierarchyNodeDescendant derived from Xafari.DC.HierarchyNode, it is Domain Component and it implements 4 different hierarchies.
Inheritance from PersistentDynamicObject eliminates the need to implement the logic of IList<HierarchyNodeDescendant> Children fields.
Children and Parent fields are defined for each hierarchy, HierarchyFullName field allows you to visualize the nesting.
When implementing multiple hierarchies, you must pass the hierarchy name as a parameter to the following attributes: HierarchyFullNamePropertyAttribute, ParentPropertyAttribute, ChildrenPropertyAttribute, HierarchyFullPathPropertyAttribute, HierarchyNodeNamePropertyAttribute.
Obtained Domain Component need to register in module:
1
2
3
4
5
public override void Setup(XafApplication application){
base.Setup(application);
XafTypesInfo.Instance.RegisterEntity("HierarchyNodeDescendant", typeof(HierarchyNodeDescendant));}
public override void Setup(XafApplication application)
{
base.Setup(application);
XafTypesInfo.Instance.RegisterEntity("HierarchyNodeDescendant", typeof(HierarchyNodeDescendant));
}
3. HierarchicalClassifierItemDescendant Domain Component derived from Xafari.BC.DC.HierarchicalClassifierItem:
[DomainComponent]public interface HierarchicalClassifierItemDescendant : Xafari.BC.DC.HierarchicalClassifierItem{[ParentProperty]
HierarchicalClassifierItemDescendant Parent {get;set;}[ChildrenProperty][BackReferenceProperty("Parent")]
IList Children {get;}[RuleFromBoolProperty("IsValidParentDC", DefaultContexts.Save, "Нельзя выбрать самого себя в вышестоящие")][NonPersistentDc][MemberDesignTimeVisibility(false)][Browsable(false)]
bool IsValidParent {get;}}[DomainLogic(typeof(HierarchicalClassifierItemDescendant))]publicclass DCHierarchyNodeObjectLogic : DomainLogicBase
{public DCHierarchyNodeObjectLogic(HierarchicalClassifierItemDescendant instance): base(instance){}public static bool Get_IsValidParent(HierarchicalClassifierItemDescendant instance){
return HierarchyNodePersistentHelper.CheckCircularReference(instance);}}
[DomainComponent]
public interface HierarchicalClassifierItemDescendant : Xafari.BC.DC.HierarchicalClassifierItem
{
[ParentProperty]
HierarchicalClassifierItemDescendant Parent { get; set; }[ChildrenProperty]
[BackReferenceProperty("Parent")]
IList Children { get; }[RuleFromBoolProperty("IsValidParentDC", DefaultContexts.Save, "Нельзя выбрать самого себя в вышестоящие")]
[NonPersistentDc]
[MemberDesignTimeVisibility(false)]
[Browsable(false)]
bool IsValidParent { get; }
}[DomainLogic(typeof(HierarchicalClassifierItemDescendant))]
public class DCHierarchyNodeObjectLogic : DomainLogicBase
{
public DCHierarchyNodeObjectLogic(HierarchicalClassifierItemDescendant instance) : base(instance) { }public static bool Get_IsValidParent(HierarchicalClassifierItemDescendant instance)
{
return HierarchyNodePersistentHelper.CheckCircularReference(instance);
}
}
This implementation only requires the declaration of Parent and Children properties. To exclude the situation when node sets himself as a parent, the IsValidParent property has been declared. Thus it was possible to avoid infinite loops.
Complete sample project is available at HierarchyNode.
In case you have any other questions regarding hierarchical data implementation in Xafari Framework, just contact us.