How is the best way to pass object, values or results between x-layer classes?

A

andrea

Sorry for the stupid question, I know, but sometimes is necessary starts
from the basic.
I don't know how to pass the result of a method generated from a DAL class
to a BL class
returning the results as it is.

I mean, for instance, something like this.

namespace DAL
{
public class Book
{
....
}

public class Books
{
....
public <List>Book GetList()
{
.....
}
}
}

namespace BL
{
public class Book
{
same structure as DAL
}

public class Books
{
public <List>Book GetList()
{
Here I need to istanciate a new DAL object and get the result of
getList function.
}
}
}

I know this is the basic of OOP programming, but I'm learning ... and book
always says that you can't or mustn't ... but never says how to solve.

I know that is impossibile to return a different type since the returning
object doesn't share the same interface, but I've tried to implement the
interface as well as the inheritance with no good result.
Can someone be so kindly try to explain me in a simple way or provide a short
code to analize and that help me to learn my errors?

Thank you
Andre
 
J

Joanna Carter [TeamB]

"andrea" <[email protected]> a écrit dans le message de (e-mail address removed)...

| Sorry for the stupid question, I know, but sometimes is necessary starts
| from the basic.
| I don't know how to pass the result of a method generated from a DAL class
| to a BL class
| returning the results as it is.
|
| I mean, for instance, something like this.
|
| namespace DAL
| {
| public class Book
| {
| ....
| }
|
| public class Books
| {
| ....
| public <List>Book GetList()
| {
| .....
| }
| }
| }
|
| namespace BL
| {
| public class Book
| {
| same structure as DAL
| }
|
| public class Books
| {
| public <List>Book GetList()
| {
| Here I need to istanciate a new DAL object and get the result of
| getList function.
| }
| }
| }

Your first problem is that the Book class in namespace BL is not the same as
the Book class in namespace DAL.

Normally, a DAL is instantiated as a Singleton or is designed as a static
class of static methods. The method fro retrieving a list can be declared as
:

public static class DAL
{
...

public static List<T> GetList()
{
// create list and populate it using reflection
}
}

You really don't need a Books class as this is covered by using a List<Book>
list.

Your calling code should look something like this :

{
List<Book> books = DAL.GetList<Book>();
}

Joanna
 
A

andrea

Thanks for your quickly reply Joanna.
I need some clarification about it ....

J> Your first problem is that the Book class in namespace BL is not the
J> same as the Book class in namespace DAL.
I know ... they are two assemblies, and this is the real important thing.

J> Normally, a DAL is instantiated as a Singleton or is designed as a
J> static class of static methods. The method fro retrieving a list can
J> be declared as :
Well a Singleton class sounds good. I imagine that it can be right in winform
scenario,
but in webform I suppose that it doesn't matter as DAL is ... singleton or
not, every time
the page ends the loading every object has died.

J> public static List<T> GetList()
J> {
J> // create list and populate it using reflection
J> }

Here I don't understand why you speak about reflection. Can you post a sample
or
something that let me better undestand?

J> You really don't need a Books class as this is covered by using a
J> List<Book> list.
Here the black hole ... if I don't need the Book class, how can my list know
of what type
is it? You mean the BL book class?


Thanks
Andrea
 
A

andrea

Something like this?

using System;
using System.Collections.Generic;

namespace DAL
{
public class book
{
public book()
{
_author = "Eric Baldwin";
_title = "The big panter";
}

public string Author
{
get { return _author; }
set { _author = value; }
}

public String Title
{
get { return _title; }
set { _title = value; }
}

private string _title;
private string _author;
}

public class Class1: List<book>
{
public Class1(){}

public List<book> test()
{
List<book> c = new List<book>();

for (int i = 0; i <= 5; i++)
{
c.Add(new book());
}

return c;
}
}
}

namespace BL
{
using dl = DAL;

public class Class1
{
public Class1()
{ }

public List<dl.book> test()
{
dl.Class1 x = new DAL.Class1();
List<dl.book> lst = x.test();

return lst;
}
}
}

namespace GUI
{
using b = BL;
using a = DAL;

public class Test
{
[STAThread]
static void Main()
{
b.Class1 x = new b.Class1();
List<a.book> lst = x.test();
}
}
}

What is strange for me is that GUI should has the DAL assembly referenced.
Is this the right way to accomplish the task?

Thanks
Andrea
 
J

Joanna Carter [TeamB]

"andrea" <[email protected]> a écrit dans le message de (e-mail address removed)...

| I know ... they are two assemblies, and this is the real important thing.

But you must not declare a type in two places as that will give you two
separate and distinct types.

Every type is distinguished by its fully qualified name, including the
namespace that it is in. So a type declared in one namespace is a totally
different type from one with the same name in another namespace. You cannot
assign/cast/convert one to the other.

| Well a Singleton class sounds good. I imagine that it can be right in
winform
| scenario,
| but in webform I suppose that it doesn't matter as DAL is ... singleton or
| not, every time
| the page ends the loading every object has died.

Maybe objects might die, but that doesn't mean that the factory has to die
as well.

| J> public static List<T> GetList()
| J> {
| J> // create list and populate it using reflection
| J> }
|
| Here I don't understand why you speak about reflection. Can you post a
sample
| or
| something that let me better undestand?

public static List<T> GetList()
{
Type[] genericParams = new Type[] { typeof(T) };

Type listType = typeof(List<>).MakeGenericType(genericParams);

IList<T> result = (Ilist<T>) Activator.CreateInstance(listType);

// populate list by getting data from storage and creating objects of type
T
// e.g.
foreach(....)
{
T newItem = new T();
// set properties using the PropertyInfos available from the type of T
result.Add(newItem);
}
return result
}

| Here the black hole ... if I don't need the Book class, how can my list
know
| of what type
| is it? You mean the BL book class?

No, I said you don't need the Books class that you were trying to derive
from List<Book>. You can simply use List<Book> without deriving from it.

Joanna
 
J

Joanna Carter [TeamB]

"andrea" <[email protected]> a écrit dans le message de (e-mail address removed)...

| Something like this?

| public class Class1: List<book>

You simply do not need to derive from List<Book>, just use it as it is in
the business layer.

The DAL doesn't need to know anything about any of the business classes,
look at the example of using reflection to create lists and objects in my
other posts.

| namespace BL
| {
| using dl = DAL;
|
| public class Class1
| {
| public Class1()
| { }
|
| public List<dl.book> test()
| {
| dl.Class1 x = new DAL.Class1();
| List<dl.book> lst = x.test();
|
| return lst;
| }
| }
| }

using DALnameSpace;

namespace BL
{
public class Book
{
...
}

public class Class1
{
public List<Book> Test()
{
return DAL.GetList<Book>();
}
}
}

| namespace GUI
| {
| using b = BL;
| using a = DAL;

Don't use this "using" syntax, it is not necessary. Just put the urdinary
using statements in the module above the namespace declaration.

| public class Test
| {
| [STAThread]
| static void Main()
| {
| b.Class1 x = new b.Class1();
| List<a.book> lst = x.test();
| }
| }
| }

using BL;

namespace GUI
{
public class Test
{
[STAThread]
static void Main()
{
Class1 x = new Class1();
List<Book> lst = x.test();
}
}
}

| What is strange for me is that GUI should has the DAL assembly referenced.
| Is this the right way to accomplish the task?

As you can see from the above code, you don't need to access the DAL from
the GUI.

Joanna
 
A

andrea

Ok thanks. Some more question.

J> Don't use this "using" syntax, it is not necessary. Just put the
J> urdinary using statements in the module above the namespace
J> declaration.

Ok for not using alis ... but what exactly is the difference of put using
into the namespace or above
it? I see a lot of code that use both ... but no lines of any books I'm reading
explain the difference
to put it inside or outside. Just use (the books) outside, but I see a lot
of big projects that use it
inside, so I've started to think about possible mistakes using outside.


There always that I cannot understand. Below your code

public class Class1
{
public List<Book> Test()
{
return DAL.GetList<Book>();
}
}
}

I tried to do this ... but pressing comma after dal, doesn't display me the
GetList Method, but the two classes
and choosing the right one doesn't expose the GetList method.

By the way, the solution that I've found is to implement an external class
with the entities that is shared
either from the DAL or BL or GUI. An interface and a class ... in this way
it should be more OOP than ever.
Is it right?


Thanks.
Andre
 
J

Joanna Carter [TeamB]

"andrea" <[email protected]> a écrit dans le message de (e-mail address removed)...

| Ok for not using alis ... but what exactly is the difference of put using
| into the namespace or above
| it? I see a lot of code that use both ... but no lines of any books I'm
reading
| explain the difference
| to put it inside or outside. Just use (the books) outside, but I see a lot
| of big projects that use it
| inside, so I've started to think about possible mistakes using outside.

Here is an example of the difference :

// module ObjectBroker.cs

namespace Carter.Framework.OPF
{
public class ObjectBroker
{
...
}
}

// module Customer.cs

using Carter.Framework.OPF // outside

namespace Carter.Framework.Business
{
using OPF; // inside

public class Customer
{
...
}
}

You can specify a partial namespace within another namespace that shares the
first parts of that namespace. What you do seems to be down to personal
taste; at least I don't know of any guidance as to which is more correct.

| There always that I cannot understand. Below your code
|
| public class Class1
| {
| public List<Book> Test()
| {
| return DAL.GetList<Book>();
| }
| }
| }
|
| I tried to do this ... but pressing comma after dal, doesn't display me
the
| GetList Method, but the two classes
| and choosing the right one doesn't expose the GetList method.

That is because your example uses DAL as a namespace and my example uses DAL
as a class in another namespace. My code was meant as a partial example and
was not designed to compile by copying into your code.

| By the way, the solution that I've found is to implement an external class
| with the entities that is shared
| either from the DAL or BL or GUI. An interface and a class ... in this way
| it should be more OOP than ever.
| Is it right?

No, you should not do things like this, it is not necessary if you make
correct use of reflection, which is well-designed in .NET to give you a
good OO approach :)

Business classes should be able to talk to the data layer.

The UI layer *should not* be able to talk to the data layer

Both the data and UI layers do not need to know anything about the business
classes as they should use reflection to examine the objects to
store/retrieve/display them.

Joanna
 
A

andrea

There is something that I've again difficult to understand. If my way (dll
that expose an interface or a class) isn't practiseable ... how can I return
a book obeject via reflection.

I suppose thatin the DAL I should have a book ... so in the BL get the list
of book via reflection ... but what for gui ?
Should I use always the reflection??

Thank you Andre
 
J

Joanna Carter [TeamB]

"andrea" <[email protected]> a écrit dans le message de (e-mail address removed)...

| There is something that I've again difficult to understand. If my way (dll
| that expose an interface or a class) isn't practiseable ... how can I
return
| a book obeject via reflection.

Why do you say that you can't create a DLL that exposes a class or interface
?

Without generics, you would return an instance in an Object reference; using
generics, you return the instance in the <T> reference.

Activator.CreateInstance(Type) returns an Object of the given type;
Activator.CreateInstance<T>() returns an instance of whatever type you
passed to the T parameter.

Simply pass the type to the DAL and then use Activator in the DAL to create
instances. You don't need to know anything about the Book class in the DAL,
it is implicit in the Type parameter.

Just for this example, write everything in the same file and namespace, just
to get the idea of how things work; you can separate the classes out later.

public class Book // business layer
{
private string title;
private string author;

public string Title
{
get { return title; }
set { title = value; }
}

public string Author
{
get { return author; }
set { author = value; }
}
}

public static class DataBroker // DAL
{
public static object CreateObject(Type objType)
{
return Activator.CreateInstance(objType);
}

public static T CreateObject<T>()
{
return Activator.CreateInstance<T>();
}
}

public class Test // business layer
{
Book a = (Book) DataBroker.CreateObject(typeof(Book));

Book b = DataBroker.CreateObject<Book>();
}

So, you see that the DataBroker (DAL) doen't need to know anything at all
about the type of object being created, it uses the type passed in to deduce
this.

| I suppose thatin the DAL I should have a book ... so in the BL get the
list
| of book via reflection ... but what for gui ?
| Should I use always the reflection??

Depending on what you want to do in the GUI, you can use the Book class from
the business layer or you can use reflection to write generic GUI components
that know how to handle any type. This is what the Binding class does when
it links a control to a property of an object.

Joanna
 
A

andrea

Joanna,

I'm in debt with you (So if you pass here in Italy ... please give me a call).

You are the first the finally let me understand my error and explained as
I really need.
Simple and with a working sample ...

Now the things has a lot of sense. But I 've a bit of confunsion again.
I cannot imagine a working scenario.

I start from this assumption (that is the 3-tier model).

DAL -> BAL -> GUI -> BAL -> DAL
And nothing more.


This mean that I get a Dataset of whatever I need to DAL and pass it back
to BAL
BAL has a definition of the object Book (or whatever it should be), read
the dataset
do all it works (in my case preapare a List<Book>) and return it to GUI that
just read it.

So in few words:

GUI call a List<Book> Bal.GetList()
the method call a DAL, DAL return the dataset, BAL read and assign to the
returning list.
Right?

If yes, I cannot understand why in your sample from BAL you create an object
of type book
letting know to DAL about the book itself.
DAL cannot work with the type book, at least, I've tried and got only error.

Trying to use one of the two Activator, let me get an object of type X that
comes
from external caller. It's a strictly-typed object and compiler know of what
type is
but if I try to do something like this in IDE, I got compile error since
b is a generic
object.

// DAL

public List<T> GetList<T>()
{
Object b = Activator.CreateInstance(typeof(T));
List<T> lst = new List<T>();

b.Author = "pippo"; // b for the IDE is a generic object

.......

return lst;
}


I believe in your patience. Sorry.

Andrea
 
J

Joanna Carter [TeamB]

"andrea" <[email protected]> a écrit dans le message de (e-mail address removed)...

| Now the things has a lot of sense. But I 've a bit of confunsion again.
| I cannot imagine a working scenario.
|
| I start from this assumption (that is the 3-tier model).
|
| DAL -> BAL -> GUI -> BAL -> DAL
| And nothing more.
|
|
| This mean that I get a Dataset of whatever I need to DAL and pass it back
| to BAL
| BAL has a definition of the object Book (or whatever it should be), read
| the dataset
| do all it works (in my case preapare a List<Book>) and return it to GUI
that
| just read it.

Not quite. You should not be getting the Dataset from the DAL, instead, you
should be getting the DAL to retrieve a Dataset and then populate the list
from that Dataset before returning it to the business layer (in the GetList
method)

| So in few words:
|
| GUI call a List<Book> Bal.GetList()
| the method call a DAL, DAL return the dataset, BAL read and assign to the
| returning list.
| Right?

Not necessarily. If you use a proper GUI framework, then the business layer
can ask the GUI layer for a "Presenter" for the list or object that it has
already retrieved from the DAL. As I said, don't get the Dataset from the
DAL, fill the list from a Dataset inside the DAL's GetList method.

| If yes, I cannot understand why in your sample from BAL you create an
object
| of type book
| letting know to DAL about the book itself.
| DAL cannot work with the type book, at least, I've tried and got only
error.

I didn't let the DAL know about the type Book, I used either an Object or
the <T> parameter to return the newly created Book, but the DAL only knew
that it was creating an Object. It was only in the business layer that I
assigned the result of the CreateObject method to a Book.

| Trying to use one of the two Activator, let me get an object of type X
that
| comes
| from external caller. It's a strictly-typed object and compiler know of
what
| type is
| but if I try to do something like this in IDE, I got compile error since
| b is a generic
| object.
|
| // DAL
|
| public List<T> GetList<T>()
| {
| Object b = Activator.CreateInstance(typeof(T));
| List<T> lst = new List<T>();
|
| b.Author = "pippo"; // b for the IDE is a generic object

I'm sorry but you can't treat these objects as strictly typed inside the
DAL.

In these kind of situations, it is usual to create a "TypeMap" so that you
can map types to tables and properties to fields. This allows you to use
different names for fields and properties, etc.

For example, your Book class has the following properties :

Book
Author
Title
ISBN

....but your database has the following columns :

T_BOOK
C_AUTHOR
C_TITLE
C_ISBN

Now you can use a Dictionary<Type, TableMap> to hold the details of the
tables
that match certain types.

public class TableMap
{
private string name;

private Dictionary<string, string> columns = new Dictionary<string,
string>();

public TableMap(string name)
{
this.name = name;
}

public string Name
{
get { return name; }
}

public void AddColumn(string propertyName, columnName)
{
if (! columns.ContainsKey(propertyName))
columns.Add(propertyName, columnName);
}

public string GetColumn(string propertyName)
{
return columns[propertyName];
}
}

public static class DAL
{
private static Dictionary<Type, TableMap> tables = new Dictionary<Type,
TableMap>();

public static void RegisterType(Type type, string tableName)
{
TableMap newItem = null;
if (! tables.ContainsKey(type))
{
newItem = new TableMap(tableName);
tables.Add(type, newItem);

/// alternative 1
// here you need to access something like an XML file that contains a list
of
// propertyName=columnName pairs and iterate through them, adding columns
// to the newly created Table object

string columnName;

foreach(string propertyName in /*XMLListing*/)
{
columnName = // get value from XMLListing
newItem.AddColumn(propertyName, columnName);
}

/// alternative 2
// or you can iterate through the properties of the type

PropertyInfo[] propInfos = type.GetProperties();

string columnName;

foreach(PropertyInfo property in propInfos)
{
columnName = "C_" + propertyName;
newItem.AddColumn(property.Name, columnName);
}
}

public static string GetTableName(Type type)
{
return tables[type].Name;
}

public GetColumnName(Type type, string propertyName)
{
return tables[type].GetColumnName(propertyName);
}

public T GetObject<T>()
{
T result = Activator.CreateInstance<T>();

Dataset ds = // create dataset from


PropertyInfo[] propInfos = typeof(T).GetProperties();
foreach(PropertyInfo pi in propInfos)
{

}
}
}

There is more to do but if I did it all, where would the fun be for you :)

Does this help ?

Joanna
 
A

andrea

Sorry didn't read the posts again.
It's quite diffucult now to understand, expecially because I've used a different
approach.

I suppose that could be better start another thread, or continue by private
conversation,
to avoid user annoyance with this stupid (but important argument) that I
cannot able to
digest.

My e-mail is moroandrea at tiscali dot it

Ciao
Andre
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top