Link to home
Start Free TrialLog in
Avatar of Autofreak
Autofreak

asked on

Class Model

Hello All,
                 I am creating a class called Accounts for my data hub purposes and I will need a few subclasses in that class. Say they will be transactions and positions. They will look like following:

Accounts(acc#).transactions(,,,,  ).mehtods,properties , etc .....     sort of the same logic as in Excel                         workbooks(name).sheets. methods & properties

I know how to create a single class but never dealt with an object model. Can you please show me how?


Thanks,
Sergei
Avatar of GENTP
GENTP

class Account
{
 private Transaction myTrans;

public Account( )
{
 myTrans = new Transactions();
}

public Transaction Transactions
{
 get{ return myTrans;}
 set { myTrans = value;}
}

}

class Transactions
{
 public int MyMethod()
{
 return 0;
}
}

void main()
{
 Account account = new Account();

// Example
int x = account.Transactions.MyMethod()
}
Oops in the Account class it should be:

public Transactions Transaction
{
 get{ return myTrans;}
 set { myTrans = value;}
}
Avatar of Autofreak

ASKER

Hi,
     I am not sure I see what I asked for and would like to try to apply this sulurion on a real problem.
Say, we have a list of accounts in a ComboBox and the user choses ,for eg. acc# 1000, to look up the number of shares of ABC stock in that portfolio. Tha portfolio data is in a SQL Server table and looks like the following

table1

account     security      shares
1000          AAA           100
1000          ABC            50
1000          AAV            52  

In the client code I would like to access the number of shares = 50 for ABC

it will probably look like

int shares = account.security.shares with prior instantiating of the required objects
OR
int shares = account(1000).security("ABC").shares


Could you please make suggestions on the class implementation strategies for this sort of problem

Thanks
Serge

You could try something along the lines of the following to achieve the
   int shares = account(1000).security("ABC").shares
type of syntax.

Unfortunately there's a mix of bracket types ( square and round ) in the syntax, but I'm sure this can be ironed out.  The code example below might contain some errors as I don't have a C# compiler to hand to check it, but it gives a general principal, and some ideas...


public MyClass
{
  public void DoGet()
  {
    AccountsAccessor account = new AccountsAccessor();

    account[1000].Security("ABC").Shares;
  }
}

public class AccountHolding
{
  double m_holdingQty;
  string m_stockCode;

  public AccountHolding(int accNo, string stockCode)
  {
    this.LoadData(accNo, stockCode);
  }

  public double Shares
  {
    get { return this.m_holdingQty; }
  }
}

public class Account
{
  int m_accNo;

  public AccountHolding Security(string stockCode)
  {
     return GetAccountHoldingForStock(this.m_accNo, stockCode);
  }

  private AccountHolding GetAccountHoldingForStock(int accNo, string stockCode)
  {
    // Query the Db to return the relevant data for the account and stock
    return new AccountHolding(accNo, stockCode);
  }
}

public class AccountAccessor
{
  private Dictionary<int, Account> m_accList;
  private bool m_useCache = true;

  public Account this[int accNo]
  {
    if (m_useCache)
    {
      return this.m_accList[accNo];
    }
    else
    {
      return this.FetchAccountDataFromDb(accNo);
    }
  }
}


weechap
Ok weechap,
                   I am gonna try it and come back with the result.

Regards
Serge
weechap,
                AccountAccesor Class doesn't have a constructor. Do you mean it do use the default one. Also, I don't quite understand the Account method and its syntax "public Account this[int accNo] " and neither does C#. As well, what method does this.FetchAccountDataFromDb reference? I don't see a method by the name in the code you supplied. Is it a member of .Net Library?

Thanks
Serge
             I figured out that a Get property needs to be added to AccountAccessor Class. this.FetchAccountDataFromDb  is still an unknown reference. Could you please provide explanation for the code, I am not sure I get everything, Class AccountAccessor in particular and the use of Dictionary.

Thanks
Serge


ASKER CERTIFIED SOLUTION
Avatar of weechap
weechap

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ok Excellent, working on it.
Regards,
Serge
Hello weechap,
                         I got one bug "Object reference not set to an instance of an object"  that is raised in Class Programm on -----> double shares = account[1000].Security("ABC").Shares; -----> pointing to '.Security("ABC")' portion when execution returnes to the line after processing this line ------>return this.m_accList[accNo] as Account; -----> in the read-only propery (AccountAccessor Class).


Could you also please explain the below property and how it works, and its role.


public Account this[int accNo]
          {
               get
               {
                    if (m_useCache)
                    {
                         return this.m_accList[accNo] as Account;
                    }
                    else
                    {
                         return this.FetchAccountDataFromDb(accNo);
                    }
               }
          }




Thank you,
Serge
Buy the way, the program compiles fine, it's the run-time when the bug comes up.
Serge
No worries,

The public Account this[int accNo] property allows you to read and return account data for a given account number value (accNo).
The m_useCache value is simply there to illustrate how you might implement some sort of caching mechanism to improve performance, and it is entirely optional.  Your null reference exception is probably as a result of this feature.  To be safe, you could change the code to be more simple:

  public Account this[int accNo]
  {
    get
    {
      return this.FetchAccountDataFromDb(accNo);
    }
  }

You could call the FetchAccountDataFromDb() method directly in your code, but the this[] property provides a more excel like property.  For example the following would produce the same result (with no caching code):

     class Program
     {
          static void Main(string[] args)
          {
               AccountAccessor account = new AccountAccessor();

               double shares = account[1000].Security("ABC").Shares;
          }
     }

And:

     class Program
     {
          static void Main(string[] args)
          {
               AccountAccessor account = new AccountAccessor();

               double shares = account.FetchAccountDataFromDb(1000).Security("ABC").Shares;
          }
     }

Notice that the difference is the syntax used when reading accounts from the AccountAccessor class.

Does this help at all?
weechap
That's cool, I was able to run it. A few more questions on data retrieval.

1. The result of the string  --> double shares = account[1000].Security("ABC").Shares;

is a bouble number that should be assigned to  this.m_holdingQty in the method below. I assignes 500 arbitrarily to get the result other than 0.

private void LoadData(int accountNumber, string StockCode)
        {
            this.m_accNo = accountNumber;
            this.m_stockCode = StockCode;
            this.m_holdingQty = 500;

            // Load the holding's data from the database or where ever the data is held.
        }


 My question is (and it may go beyond the original quetion's scope but is still an integral its part) - To get this value, do I just retrieve a recordset usin ADO.NET like
SELECT shares
FROM holdings_table
WHERE account=1000 AND security="ABC"
GROUP BY security

or did you mean somthing different  ?

2. I don't see that we use the Hashtable anywhere, what role did you intend to give it?


 
1.  I think you're on the right lines with what you're saying.  Unfortunately I don't know too much about ADO.NET, but I'd expect the load data method to be something like:

     private void LoadData(int accountNumber, string StockCode)
     {
          this.m_accNo = accountNumber;
          this.m_stockCode = StockCode;

          // Load the holding's data from the database or where ever the data is held.

          // Construct an SQL query to read the Account Holding data
          string sqlQuery = string.Format("SELECT ht.shares FROM holdings_table ht WHERE ht.account = {0} AND ht.security = '{1}'", this.m_accNo, this.m_stockCode);

          // Now create a database connection, open it and execute the query.  
          // The resulting dataset should contain the number of shares in this holding.
          // Set the value of this.m_holdingQty from the value in the dataset
     }

2. The hashtable was a part of the caching mechanism.  You can ignore it if you want.
Thank you, it's getting clearer, your explanations get me where I hopped I would get .

             I am going to ask you one question that may seem not so clear though. Thing is, I am fairly new to C# and the real OOP overall like some of the technics I saw you using go beyong the material I have covered so far. I am thrilled at how the Classes you built work and imtuitively understand the archetectural idea behind the code but I would like to clarify a few things to know for sure what is going on.

             For instance, I 've gone over inheritance & polymorphism, looked at composition and how it is different from the former. However, the way your classes are designed cannot be explained by what I have seen so far. For example, starting with Class AccountAccessor this is what I observe.

in Class  Program we start with alocating memory for a new object account of AccountAccessor Class that has no data/instance variables (given the no-cache version). Execution jumps right to the next line-----> double shares = account[1000].Security("ABC").Shares; -----<  

public Account this[int accNo]  property in not a usual accessor/property such as, say, public int Property {get {return property;}} where <property> would be a <private int property> instance variable of AccountAccessor Class. Instead, public Account this[int accNo] refers to AcountAccessor Class itself -- this[int accNo] ---  and defines this reference as Account Class type. The AccountAccessor Acass's  get property ends with < return new Account(accNo); that does somthing to account object such that we can access <public AccountHolding Security(string stockCode)>  method of Account Class thru <account[1000].> part of <double shares = account[1000].Security("ABC").Shares;> In this case, thru get propery <return new Account(accNo);>  what happens to account object? Has it morphed into Account Class's object such as account[1000]?


                    This pattern repeats in Account class where methods Security and GetAccountHoldingForStock are of AccountHolding Class the class to which <public AccountHolding Security(string stockCode)> method refers to when in the last step of <account[1000].Security("ABC")> it executes a line like this <return new AccountHolding(accNo, stockCode);> Does it mean that now account[1000].Security("ABC") can be considered as AccountHolding class object and thus can access the Class's property <public double Shares>???


Like I said, I sort of see how it's intended to work but need to get to the bottom of the technology. Sort of lookes like backword polymorphism where classes don't inherit explicely but use other classes' functionality by becoming those classes' objects after some work has been done while enjoying being the preceding class's instance.  

Could you please comment on it.

Regards,
Serge


 
Wow, you're really into this stuff!

The code example I gave was really only an illustration of how you could achieve what I thought you wanted.  There are lots of potential improvements that can be incorporated in it, but I'll leave those for you to implement !

The this[int index] property is unusual.  It is conventionally used to provide indexed access to an array or collection of objects.  The AccountAccessor class is intended as the way in which Account data is constructed.  In this way it is kind of behaving like a Factory (search for Factory Pattern on google).  The AccountAccessor object contains no data in this example, but in a full application it might contain caching data or db connection data, etc.  It's likely that the AccountAccessor class would be implemented using a Singleton pattern.

You asked the question "What happens to the Account object?".  I'm not sure what you mean by this exactly.  An instance of the Account class is created in the AccountAccessor.  This is returned to the Main method where the Security method is called.  This returns an instance of AccountHolding, which has a property Shares.  As an illustration the Main method can be re-written as:

      static void Main(string[] args)
     {
          // Create an accountFactory so that we can read account data
          AccountAccessor accountFactory;
          accountFactory = new AccountAccessor();

          // Read account number 1000 and store it in a local variable (myAcc)
          Account myAcc;
          myAcc = accountFactory[1000];          // <- Method call 1

          // Read the AccountHolding data for stock ABC from account number 1000 (myAcc) and store the
          // AccountHolding data in a local variable (holding)
          AccountHolding holding;
          holding = myAcc.Security("ABC");          // <- Method call 2

          // Now read the number of shares that the holding has
          double shares;
          shares = holding.Shares;          // <- Method call 3
     }

---------------
> This pattern repeats in Account class where methods Security and GetAccountHoldingForStock
> are of AccountHolding Class the class to which <public AccountHolding Security(string stockCode)>
> method refers to when in the last step of <account[1000].Security("ABC")> it executes a line
> like this <return new AccountHolding(accNo, stockCode);> Does it mean that now
> account[1000].Security("ABC") can be considered as AccountHolding class object and thus can
> access the Class's property <public double Shares>???

Yes.
---------------

I'm not sure what you mean by "backwards polymorphism" exactly. The code example I gave is fairly simple, and it does nothing unusual really.  The line:

     double shares = account[1000].Security("ABC").Shares;

...contains three separate method calls (see the expanded example above).  Each method call returning an instance of a class that can be used in a subsequent call.  The nice thing with C# is that it allows us to wrap up a number of method calls into one line of code.  This can be handy if we want to reduce the amount of code, but it can also be confusing when trying to work out what is going on.

weechap
Thank you weechap, I got a notch taller after talkin to you, gimme some time and we will probably continue our discussion in a fresh Q. This one is a strong A++ , thanks for the patience and understanding.

Serge  
No worries
By the way,
                  there's no e-mail in your profile, wanna give it to me case I need your advice? Perhaps alerting you to Q's like this one is rational.  

Cheers,
Serge