unable to traverse using IParent interface

unable to traverse using IParent interface

Old forum URL: forums.lhotka.net/forums/t/12821.aspx


acheema posted on Monday, January 26, 2015

Hi guys, we are using Csla for our business objects, currently using version 3.8.4. There was a requirement to get property value into one of Child's Child object. I was trying to use IParent interface to climb up in hierarchy. But it seems to me i am doing some thing wrong or may be i missed something. Please find attached console test application. i commented out the access path in objB.CheckBsParent() method.

A quick response will be appreciated.

 

Regards.

ajj3085 replied on Monday, January 26, 2015

You'll need to define your own internal property and return "this" as either IParent or as the concrete type.  In your case probably the concrete type at least in the class that has the property you want.   this is easier in later Csla versions as IParent defines a Parent property on the interface, but in your version it doesn't.

JonnyBee replied on Monday, January 26, 2015

Hi,

As Andy said - this is implemented in the IParent iterface in newer versions of CSLA.

I always prefer to have intermediate base classes that allows me to do this kind of modifications. You could then add your own public MyParent property to all actual classes and use this to traverse the structure.

Another option is to use Reflection (as long as you are on .NET) to get internal or private properties. CSLA has MethodCaller class that makes this a lot easier or use FasterFlect, http://fasterflect.codeplex.com or NuGet: http://www.nuget.org/packages/fasterflect/

Using MethodCaller:

public void CheckBsParent()
{
  var chLstB = (this.Parent as ChildLstB);
  var chA = MethodCaller.CallMethod(chLstB, "get_Parent"as ChildA;
  var chLstA = MethodCaller.CallMethod(chA, "get_Parent"as ChildLstA;
  var root = MethodCaller.CallMethod(chLstA, "get_Parent"as RootObj;
}
(note: you must use CallMethod to get the property as MC.CallPropertyGetter only sees the available properties)
 
Using FasterFlect:
public void CheckBsParent() {   var chLstB = (this.Parent as ChildLstB);   var chA = chLstB.GetPropertyValue("Parent"as ChildA;   var chLstA = chA.GetPropertyValue("Parent"as ChildLstA;   var root = chLstA.GetPropertyValue("Parent"as RootObj; }

acheema replied on Tuesday, January 27, 2015

Thank you Andy, Jonny and Wilfreds, for quick response Star. Really appreciated.  I had implemented like Wilfred's sort of code in my BO's, but never get a chance to test it. Now when it was required, i was unable to get through it. And also could not find any thread where i can see IParent implementation. Now at-least we have one thread where one can find code to test. 

Thanks once again.

ajj3085 replied on Tuesday, January 27, 2015

I don't think you really need to keep the parent in its own field and gave a SetParent.  Each class already has a Parent property which you can just cast.  That'd keep implementation simpler.

[Serializable()]
  public partial class ChildLstB : BusinessListBase<ChildLstB, ChildB>
  {
      internal ChildA ListParent
      {
          get { return (ChildA)Parent; }
      }


      internal static ChildLstB NewChildLstB()
    {
      ChildLstB obj = new ChildLstB();
      
      return obj;
    }

  }

acheema replied on Tuesday, January 27, 2015

Thanks Andy, you are right, i tested as ur code, it worked too. Thanks again.

wilfreds replied on Tuesday, January 27, 2015

This is how I do it if I'm on 3.8.3:

namespace CslaParentTst
{
  class Program
  {
    static void Main(string[] args)
    {
      RootObj root = InitBO();
      var objA = root.ChildLstA.FirstOrDefault();
      var objB = objA.ChildLstB.FirstOrDefault();

      objB.CheckBsParent();
    }

    static RootObj InitBO()
    {
      RootObj obj = RootObj.NewRootObj("100");

      ChildB objB = ChildB.NewChildB("300");

      ChildA objA = ChildA.NewChildA("200");

      objA.ChildLstB.Add(objB);

      obj.ChildLstA.Add(objA);

      return obj;
    }

  }

  [Serializable()]
  class RootObj : Csla.BusinessBase<RootObj>
  {
      protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)
      {
          ChildLstA.SetParent(this);
      }
     
    private static PropertyInfo<string> IDProperty = RegisterProperty(new PropertyInfo<string>("ID", "ID"));
    private static PropertyInfo<decimal> NoOfUnitsProperty = RegisterProperty(new PropertyInfo<decimal>("NoOfUnits", "NoOfUnits"));
    private static PropertyInfo<ChildLstA> ChildLstAProperty = RegisterProperty(new PropertyInfo<ChildLstA>("ChildLstA", "ChildLstA"));

    [System.ComponentModel.DataObjectField(true, false)]
    public string ID
    {
      get { return GetProperty(IDProperty); }
    }

    public decimal NoOfUnits
    {
      get { return GetProperty(NoOfUnitsProperty); }
      set { SetProperty(NoOfUnitsProperty, value); }
    }

    public ChildLstA ChildLstA
    {
      get
      {
        if (!FieldManager.FieldExists(ChildLstAProperty))
          LoadProperty(ChildLstAProperty, ChildLstA.NewChildLstA(this));
        return GetProperty(ChildLstAProperty);
      }
    }

    public static RootObj NewRootObj(string ID)
    {
      return DataPortal.Create<RootObj>(new SingleCriteria<RootObj, string>(ID));
    }

    [RunLocal]
    private void DataPortal_Create(SingleCriteria<RootObj, string> criteria)
    {
      LoadProperty(IDProperty, criteria.Value);
      ValidationRules.CheckRules();
    }
  }

  [Serializable()]
  public partial class ChildLstA : BusinessListBase<ChildLstA, ChildA>
  {
      [NonSerialized(), NotUndoable()]
      private RootObj mParent;

      internal RootObj ListParent
      {
          get { return mParent; }
      }

      internal void SetParent(RootObj parent)
      {
          mParent = parent;
      }
      internal static ChildLstA NewChildLstA(RootObj parent)
    {
      ChildLstA obj = new ChildLstA();
      obj.SetParent(parent);
      return obj;
    }

  }

  [Serializable()]
  public partial class ChildA : BusinessBase<ChildA>
  {
      internal new ChildLstA Parent
      {
          get { return (ChildLstA)base.Parent; }
      }

      protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)
      {
          ChildLstB.SetParent(this);
      }

    private static PropertyInfo<string> IDProperty = RegisterProperty(new PropertyInfo<string>("ID", "ID"));
    private static PropertyInfo<decimal> NoOfUnitsProperty = RegisterProperty(new PropertyInfo<decimal>("NoOfUnits", "NoOfUnits"));
    private static PropertyInfo<ChildLstB> ChildLstBProperty = RegisterProperty(new PropertyInfo<ChildLstB>("ChildLstB", "ChildLstB"));

    [System.ComponentModel.DataObjectField(true, false)]
    public string ID
    {
      get { return GetProperty(IDProperty); }
    }

    public decimal NoOfUnits
    {
      get { return GetProperty(NoOfUnitsProperty); }
      set { SetProperty(NoOfUnitsProperty, value); }
    }

    public ChildLstB ChildLstB
    {
      get
      {
        if (!FieldManager.FieldExists(ChildLstBProperty))
          LoadProperty(ChildLstBProperty, ChildLstB.NewChildLstB(this));
        return GetProperty(ChildLstBProperty);
      }
    }

    public static ChildA NewChildA(string ID)
    {
      return DataPortal.Create<ChildA>(new SingleCriteria<ChildA, string>(ID));
    }

    [RunLocal]
    private void DataPortal_Create(SingleCriteria<ChildA, string> criteria)
    {
      LoadProperty(IDProperty, criteria.Value);
      ValidationRules.CheckRules();
    }
  }

  [Serializable()]
  public partial class ChildLstB : BusinessListBase<ChildLstB, ChildB>
  {
      [NonSerialized(), NotUndoable()]
      private ChildA mParent;

      internal ChildA ListParent
      {
          get { return mParent; }
      }

      internal void SetParent(ChildA parent)
      {
          mParent = parent;
      }

      internal static ChildLstB NewChildLstB(ChildA parent)
    {
      ChildLstB obj = new ChildLstB();
      obj.SetParent(parent);
      return obj;
    }

  }

  [Serializable()]
  public partial class ChildB : BusinessBase<ChildB>
  {
   
    private static PropertyInfo<string> IDProperty = RegisterProperty(new PropertyInfo<string>("ID", "ID"));
    private static PropertyInfo<decimal> NoOfUnitsProperty = RegisterProperty(new PropertyInfo<decimal>("NoOfUnits", "NoOfUnits"));

    [System.ComponentModel.DataObjectField(true, false)]
    public string ID
    {
      get { return GetProperty(IDProperty); }
    }

    public decimal NoOfUnits
    {
      get { return GetProperty(NoOfUnitsProperty); }
      set { SetProperty(NoOfUnitsProperty, value); }
    }

    public void CheckBsParent()
    {
      var chLstB = (this.Parent as ChildLstB);
      var chA = (chLstB.ListParent as ChildA);
      var chLstA = (chA.Parent as ChildLstA);
      var root = (chLstA.ListParent as RootObj);

        //var chA = (chLstB.Parent as ChildA);
        //var chLstA = (chA.Parent as ChildLstA);
        //var root = (chLstA.Parent as RootObj);
    }


    public static ChildB NewChildB(string ID)
    {
      return DataPortal.Create<ChildB>(new SingleCriteria<ChildB, string>(ID));
    }

    [RunLocal]
    private void DataPortal_Create(SingleCriteria<ChildB, string> criteria)
    {
      LoadProperty(IDProperty, criteria.Value);
      ValidationRules.CheckRules();
    }
  }

}

 

Copyright (c) Marimer LLC