StrataFrame Forum

Subcalssing SF Business Objects

http://forum.strataframe.net/Topic29980.aspx

By Ger Cannoll - 5/16/2011

I want to start subclassing SF Buisness Objects (so I can imbed ny own Code in some of the methods)  and am not sure how to do this. I have successfully subclassed a few controls (TextBoxes, Lables) etc and they are working fine, so I am using a similar approcah for Buisness Objects.

I tried :  

public class KernelBO : MicroFour.StrataFrame.Business.BusinessLayer
{
}
My project compiles ok. I then created a new Business Object in the normal way , and went in manually and changed the generated code

from:
public partial class SquBO : MicroFour.StrataFrame.Business.BusinessLayer
to:
public partial class SquBO : KernelBaseSF.KernelBO


but got an error in compiling the Business Objects Project (KernelBaseSF.KernelBO does not contain a constructor that takes 2 arguments

What am I doing wrong here ?

 

By Sam Tenney - 5/16/2011

Hi Gerard,

There used to be an article available from this website named "Subclassing Business Objects" written by Les Pinter, but I cannot find it now.  It might help you if somebody can find it.

I wish I could help you directly, but I am still a novice.  I only remember that the procedure was not at all what I expected.  I'm sure somebody from StrataFrame will help you soon.

Sam Tenney
By Terry Bottorff - 5/16/2011

I have a copy if you want me to email it too you?
Terry Bottorff
By Ger Cannoll - 5/16/2011

Hi Terry.

Yes, Please email it.

Not sure if its the same one as an article on the LesPinter.com about Subclassing in general. I found that helpful for subclassing the standard controls, and there is also a section in there about subclassing BusinessObjects. I started reading it, but it seemd to be extremely complicated and went on to a few pages.... I was expecting it to take one or two lines to subclass.. but perhaps I am wrong , so I decided to post here in the hope that there is a simple way of subclassing Business Objects .... I presume most people subclass BUisness Objects as it is supposed to be best practise.
By Terry Bottorff - 5/17/2011

That is exactly the one it is. So no need to send it.
Sorry.
By Ger Cannoll - 5/17/2011

Hi Terry

I have had another look at the artcile and it seems to concentrate on Subclassing a specific BuisnessObject that was created in an application.

All I want to do is subclass the StrataFrame BusinesObject Class so I can insert my own specific code wherever required

Perhaps someone from SF might jump in
By Greg McGuffey - 5/17/2011

The error you are getting is likely because your base class and derived class don't have matching constructors.  I.e. the following will bomb:

public class BaseBusinessLayer : MicroFour.StrataFrame.Business.BusinessLayer
{
    //-- Default, no argument constructor inferred
}

public class DerivedBO : BaseBusinessLayer
{
    //-- Oops, what constructor of base class is to be called here?
    //    There is no constructor in BaseBusinessLayer with two constructors.
    public DerivedBO (int index, int companyID) {}
}


All you need to do is explicitly call the correct constructor of the base class:

public class DerivedBO : BaseBusinessLayer
{
    //-- Explicitly call desired constructor of base class.
    public DerivedBO (int index, int companyID)
        : BaseBusinessLayer()
    {}
}


Also, BusinessLayer (and sub-classes of it) isn't really meant to be directly instantiated. They define an interface for common data and functionality for actual BOs (i.e. BOs built via the BO mapper).  There are lots of methods/properties that will through NotImplemented exceptions if just left as-is.
By Ger Cannoll - 5/17/2011

Hi Greg.

If subclassing the SF Business Objects is not the way to go, I'm wondering whats the best way of inserting my own functionality into the SF Business Objects.

For instance, I will now have code that I want to insert in the SetDefaultValues event of a Buisness Object (following on from another thread) . I would see this going into most of my Business Objects.The code that will run will take data from another BUsiness Object and insert DataDriven values into the Business Object

So what I want to do, is Subclass the Business Object (SF One) and add in code to the SetDefaultValues event.

I could call the code from every Business Object I create,  but was looking for a more OO way of doing it
By Greg McGuffey - 5/17/2011

You're headed in the right direction.   You DO want to sub class BusinessLayer, then inherit you BOs from this. 

My comments were probably a bit confusing, as in my mind, I have classes that inherit from BusinessLayer and are intended to extend the base functionality (like you want to do with your set default values code) and then there are BOs which also inherit from BusinessLayer (or a sub class of BusinessLayer), but they are then built with the BO mapper.  However, they are all sub-classes of BusinessLayer. 

If you look in the designer file of a BO, you'll see ALL the other stuff you have to do to get a working BO. So, there is kind of this division between BusinessLayer, providing base functionality/common properties and BO, providing implementations for some of the common properties and providing data specific properties (to support data binding). BusinessLayer is exactly the place to put common code for BOs. BOs are the actual classes that interact with data and are bindable to controls. 

To get a class that you can instantiate, you need to either have the BO mapper do the work or you need to do that manually (ugh). 

//-- So, this is NOT going to work at some point
//   ...BusinessLayer has a bunch of NotImplemented methods/properties
BusinessLayer busLayer1 = new BusinessLayer();

//-- This will work, because we are providing an actual BO.
//   but only need the base functionality of the BusinessLayer.
BusinessLayer busLayer2 = new CustomersBO();

//-- And of course this will work too...
CustomersBO customers = new CustomersBO();


So, you do want to sub-class BusinessLayer and add you SetDefaultValues handler.  Then you want to change the inheritance of BOs that need this functionality as you did. You then would instantiate only BOs, though you can have BusinessLayer type variables pointing to BOs.

Is this making more sense? 
By Ger Cannoll - 5/17/2011

Ok Greg, still not clear on what I have to do to SubClass the SF BO.

My starting point was:

public class KernelBO : MicroFour.StrataFrame.Business.BusinessLayer
{
}


Is there something more I need to add in here ?

Say I go to the code (That is created from the |Business Object mapper) whcih will have code like:

public partial class SmaBO : MicroFour.StrataFrame.Business.BusinessLayer


Do I Need to change this code ?



 
By Greg McGuffey - 5/17/2011

To sub-class a BO, you are actually sub-classing the BusinessLayer as you have done. Then, you change the inherits in the BO to point to your sub-classing of the BusinessLayer.

//-- sample customized BusinessLayer
public class HelloWorldLayer : MicroFour.StrataFrame.Business.BusinessLayer
{
    public string GetGreeting()  { return "Hello World!"; }
}

//-- Change BO to inherit from this business layer.
public class HelloWorldBO : HelloWorldLayer
{
    //....
}


When doing the sub-class of BusinessLayer, you might need to explicitly implement the constructors, just calling the base constructors. 
By Ger Cannoll - 5/19/2011

I have put in constructor code when subclassing the SF buisnes object but am getting errors on Icontainer line and InitializeComponent. I basically took these snippets of code from the BuisnessObjects created ut of the Busimess Object Mapper. Not sure if I need the InitializeComponent line ??

My full Subclassing Code is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using MicroFour.StrataFrame.UI;
using MicroFour.StrataFrame.Business;
using MicroFour.StrataFrame.UI.Windows.Forms.DevEx;
using DevExpress.XtraEditors;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Runtime.Serialization;
using System.Diagnostics;
namespace KernelBaseSF
{
// 16-05-11 Subclass Business Object
public class KernelBO : MicroFour.StrataFrame.Business.BusinessLayer
{
public KernelBO()
: base()
{ InitializeComponent(); }
 
public KernelBO(Icontainer container)
: base()
{
container.Add(this);
InitializeComponent();
}
public KernelBO(SerializationInfo info, StreamingContext context)
:base(info,context)
{
InitializeComponent();
}
}


By Greg McGuffey - 5/19/2011

You do not need the initialize component. That is specific to the actual BOs.  For an extended BusinessLayer, you'd use
something like this:

public class KernelBO : MicroFour.StrataFrame.Business.BusinessLayer
{
     public KernelBO() : base() {}

     public KernelBO(Icontainer container) : base( container ) {}

     public KernelBO(SerializationInfo info, StreamingContext context) :base( info, context ) {}

}


You would then add any specific code as needed.  For instance I did a BusinessLayer to support auditing and added event handlers to add/edit/delete events of base.
By Ger Cannoll - 5/19/2011

Hi Greg. ve stripped out all the InitailizeComponent etc stuff and have it down to what you have suggested, but its coming up with a problem on Icontainer....type or namespace Icontainer could not be found.  I've included all the namespaces I think are required, including System.ComponentModel
By Greg McGuffey - 5/19/2011

Hmmm....It's in System.ComponentModel, so not sure what your problem is.  Could you post a sample of the stripped down app?
By Ger Cannoll - 5/19/2011

Hi Greg.

I removed the line and typeed it in again......and now it compiles ok without an error .

Now I want to add in functionality  (into my Bae Class) to run code in the SetDefaultValues method of the Business Object. How do I code this in in my Base Class.
By Greg McGuffey - 5/20/2011

I removed the line and typed it in again......and now it compiles ok without an error

 
Don't ya love it when that happens. I can't tell you how many hours I've wasted on things like this.....  Crazy

As to having custom code for SetDefaultValues, you would override the OnSetDefaultValues method.  You'll want to call the base method to ensure that the event gets raised for others to consume.

//-- In your base class....
protected override void OnSetDefaultValues()
{
    //-- Call base method to actually raise event for other consumers.
    base.OnSetDefaultValues();

    //-- Add you customization code.
}


Depending on your needs, you can call the base class first (as shown) which will raise the event, then execute your custom code (i.e. you want any other work to be done before you do yours) OR you can call it afterwards, meaning you want to have your custom work done before the event is raised and thus available to any consumers of the event.