PC Review


Reply
Thread Tools Rate Thread

Circular Referencing in C#

 
 
PromisedOyster
Guest
Posts: n/a
 
      15th Feb 2005
Hi

I have a situation where I want to use circular referencing. I have cut
down the example for demonstration purposes.

Say we have one executable (main.exe) and two DLLS (A1.dll and A2.dll).
Main can access classes in A1 and A2; A1 can access classes in A2.

However, I now want to access classes in A1 from A2. I cannot simply
create a third DLL as the A1/A2 assemblies use other classes within
their respective assemblies.

I believe that I can use interface classes to solve this situation.
However, to be honest, I'm not sure how?

An example would be very useful....


eg in main.exe
--------------
using A1;
using A2;

A1C1 a1c1 = new A1C1();
A2C1 a2c1 = new A2C1();


A1.DLL
------
using A2;
namespace A1
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class A1C1
{
public A1C1()
{
A2C1 c = new A2C1();
}
}
public class A1C2
{
public A1C2()
{
// I want access thi class from A2
}
}
}

A2.DLL
------

namespace A2
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class A2C1
{
public A2C1()
{
// Can access this class from A1
}
}
public class A2C2
{
public A2C2()
{
// I now want to access A1C2??????
}
}
}

 
Reply With Quote
 
 
 
 
sadhu
Guest
Posts: n/a
 
      15th Feb 2005
Hi,

Declare an interface for A1C2 in a separate assembly. Refer it from
A2. And when you pass an instance of A1C2, pass it as an interface.

Regards
Senthil

PromisedOyster wrote:
> Hi
>
> I have a situation where I want to use circular referencing. I have

cut
> down the example for demonstration purposes.
>
> Say we have one executable (main.exe) and two DLLS (A1.dll and

A2.dll).
> Main can access classes in A1 and A2; A1 can access classes in A2.
>
> However, I now want to access classes in A1 from A2. I cannot simply
> create a third DLL as the A1/A2 assemblies use other classes within
> their respective assemblies.
>
> I believe that I can use interface classes to solve this situation.
> However, to be honest, I'm not sure how?
>
> An example would be very useful....
>
>
> eg in main.exe
> --------------
> using A1;
> using A2;
>
> A1C1 a1c1 = new A1C1();
> A2C1 a2c1 = new A2C1();
>
>
> A1.DLL
> ------
> using A2;
> namespace A1
> {
> /// <summary>
> /// Summary description for Class1.
> /// </summary>
> public class A1C1
> {
> public A1C1()
> {
> A2C1 c = new A2C1();
> }
> }
> public class A1C2
> {
> public A1C2()
> {
> // I want access thi class from A2
> }
> }
> }
>
> A2.DLL
> ------
>
> namespace A2
> {
> /// <summary>
> /// Summary description for Class1.
> /// </summary>
> public class A2C1
> {
> public A2C1()
> {
> // Can access this class from A1
> }
> }
> public class A2C2
> {
> public A2C2()
> {
> // I now want to access A1C2??????
> }
> }
> }


 
Reply With Quote
 
PromisedOyster
Guest
Posts: n/a
 
      15th Feb 2005
Hi sadhu

Could you please provide me with an example of what you mean.

This would be very useful. I am not sure why there is a need for the
separate assembly?

sadhu wrote:
> Hi,
>
> Declare an interface for A1C2 in a separate assembly. Refer it from
> A2. And when you pass an instance of A1C2, pass it as an interface.
>
> Regards
> Senthil
>
> PromisedOyster wrote:
> > Hi
> >
> > I have a situation where I want to use circular referencing. I have

> cut
> > down the example for demonstration purposes.
> >
> > Say we have one executable (main.exe) and two DLLS (A1.dll and

> A2.dll).
> > Main can access classes in A1 and A2; A1 can access classes in A2.
> >
> > However, I now want to access classes in A1 from A2. I cannot

simply
> > create a third DLL as the A1/A2 assemblies use other classes within
> > their respective assemblies.
> >
> > I believe that I can use interface classes to solve this situation.
> > However, to be honest, I'm not sure how?
> >
> > An example would be very useful....
> >
> >
> > eg in main.exe
> > --------------
> > using A1;
> > using A2;
> >
> > A1C1 a1c1 = new A1C1();
> > A2C1 a2c1 = new A2C1();
> >
> >
> > A1.DLL
> > ------
> > using A2;
> > namespace A1
> > {
> > /// <summary>
> > /// Summary description for Class1.
> > /// </summary>
> > public class A1C1
> > {
> > public A1C1()
> > {
> > A2C1 c = new A2C1();
> > }
> > }
> > public class A1C2
> > {
> > public A1C2()
> > {
> > // I want access thi class from A2
> > }
> > }
> > }
> >
> > A2.DLL
> > ------
> >
> > namespace A2
> > {
> > /// <summary>
> > /// Summary description for Class1.
> > /// </summary>
> > public class A2C1
> > {
> > public A2C1()
> > {
> > // Can access this class from A1
> > }
> > }
> > public class A2C2
> > {
> > public A2C2()
> > {
> > // I now want to access A1C2??????
> > }
> > }
> > }


 
Reply With Quote
 
Bruce Wood
Guest
Posts: n/a
 
      15th Feb 2005
It would help to know what you mean by "access" A1C2 from A2C2... do
you mean accept as a parameter, create a new instance... what do you
need to do with it?

Senthil's solution is the one that applies to all situations: create a
new assembly that contains interfaces. These interfaces are contracts
that the classes in the other two assemblies agree to honour. Then each
assembly deals with the other in terms of interfaces.

However, in limited situations, you may be able to get away with
putting the interfaces in A2, which would leave you with a one-way
references from A1 to A2, but never the other direction.

Could you give more details on what you need to do?

 
Reply With Quote
 
PromisedOyster
Guest
Posts: n/a
 
      15th Feb 2005

Bruce Wood wrote:
> It would help to know what you mean by "access" A1C2 from A2C2... do
> you mean accept as a parameter, create a new instance... what do you
> need to do with it?
>
> Senthil's solution is the one that applies to all situations: create

a
> new assembly that contains interfaces. These interfaces are contracts
> that the classes in the other two assemblies agree to honour. Then

each
> assembly deals with the other in terms of interfaces.
>
> However, in limited situations, you may be able to get away with
> putting the interfaces in A2, which would leave you with a one-way
> references from A1 to A2, but never the other direction.
>
> Could you give more details on what you need to do?


I want to create an instance of the class A1C2 from A2C2

ie
public A2C2()
{
A1C2 c = new A1C2();
}

 
Reply With Quote
 
Olorin
Guest
Posts: n/a
 
      15th Feb 2005
Have you tried writing just that ?
(ok, with a using A1 statement at the top).
A1C2 does not have a field of any type in A2, so instanciating an
object of type A1C2 does not create a circular reference.... unless I'm
missing something.

HTH,
F.O.R.

 
Reply With Quote
 
Joanna Carter \(TeamB\)
Guest
Posts: n/a
 
      15th Feb 2005
"PromisedOyster" <(E-Mail Removed)> a écrit dans le message de
news: (E-Mail Removed)...

> I want to create an instance of the class A1C2 from A2C2


From an OO design perspective, what you are trying to do seems overly
complicated and has a 'bad smell' about it.

If multiple classes have such strong interdependencies, then it is likely
that they exist within the same assembly at least.

This kind of design problem is a symptom of more problems to come, as you
code becomes more and more convoluted.

Can you share some real names for these classes, so that we can advise on
the design ?

Joanna

--
Joanna Carter
Consultant Software Engineer


 
Reply With Quote
 
Ajay Kalra
Guest
Posts: n/a
 
      15th Feb 2005
If you have both classes sort of depending upon each other, why do you
have a separate assembly for each? You can make it work using
interfaces etc, but you should look into refactoring your dlls and
possibly bringing the functionality from A2 into A1 that you want in
A1.

-----------
Ajay Kalra
(E-Mail Removed)

 
Reply With Quote
 
Bruce Wood
Guest
Posts: n/a
 
      15th Feb 2005
I think I understand what the OP is trying to do. It's actually very
good design... it's just that it's a trick trying to figure out how to
do it in C#. If I'm reading this right, consider the following:

A classic three-tiered design. The UI component talks only to the
business layer, never to the data layer. The business layer
encapsulates business rules, but also knows how to talk to the data
layer to load and fetch instances of itself. The data layer would like
to be ignorant of the the other two layers, but unfortunately it can't
be, because it has to know how to build and return business objects
that it has fetched from the database.

In the end, one ends up with a circular reference between the business
layer and the data layer. The interdependence isn't really all that
strong... it's just that the data layer builds and returns business
objects (and accepts them in order to insert / update them in the
database), and the business layer knows how to call various top-level
data layer methods, usually CRUD interfaces to the database that
abstract data layer operations to business layer terms.

It's a good design, but it causes problems in C#, which doesn't allow
circular DLL references for reasons that have everything to do with how
the compiler / languages works and little (or maybe nothing) to do with
enforcing good design.

One way to solve this problem in C# is simply to abandon the division
into two DLLs. After all, your data layer and your business layer are
tightly coupled, so you're never going to use one without the other.
The division into two DLLs for two tiers may seem aesthetically
pleasing, but it really serves no practical purpose.

Another way to solve the problem is to have your business layer publish
a data layer interface, in effect saying, "These are the data layer
object signatures that I require in order to operate." Part of the
initialization of the system then becomes pointing the business layer
to the actual data layer that it is going to be using. The data layer
must then be sure to implement all of the interfaces in order that the
business layer can use it. Conceptually, what is happening here is that
your business layer is creating a demand contract: "I demand that the
data layer provide the following functionality. I will work with any
data layer that provides this functionality." So the static DLL
references become: UI layer references business layer; data layer
references business layer. The business layer references nothing but
interface definitions, and is connected to the true data layer at run
time.

You could also completely change the design and say that the data layer
returns data objects, not business objects, so calling data layer
functions returns DataSets, or DataTables, or DataRows. It then becomes
the responsibility of the business layer to put a business veneer on
this "pure data". This is more the approach that Microsoft has taken:
data layers return Data...whatever objects; Visual Studio will build
classes for you that front these DataTables, etc. It's then up to you
to build business logic around what is really just pure data. (By
subclasing the auto-generated classes? I haven't tried this yet.) In
this scenario, your UI layer has a static reference to your business
layer, and your business layer to your data layer. The data layer has
no reference to the business layer because it returns information on
its own terms, not conveniently packaged for the business layer.
Personally, I find this design a little uglier than the preceding one:
a tier should really cater to the next tier up in the hierarchy,
packaging its functions and results for the convenience of its "client"
tier. It's "bad software behaviour" to say to your calling tier,
"here's what you asked for in the form that is convenient for _me_ to
deliver it. You deal with any disconnects between that and your world
view." However, as I said, this is more how MS is doing things, so it's
worth considering.

 
Reply With Quote
 
Joanna Carter \(TeamB\)
Guest
Posts: n/a
 
      15th Feb 2005
"Bruce Wood" <(E-Mail Removed)> a écrit dans le message de news:
(E-Mail Removed)...

> A classic three-tiered design. The UI component talks only to the
> business layer, never to the data layer. The business layer
> encapsulates business rules, but also knows how to talk to the data
> layer to load and fetch instances of itself. The data layer would like
> to be ignorant of the the other two layers, but unfortunately it can't
> be, because it has to know how to build and return business objects
> that it has fetched from the database.


What you are talking about is something with which I have a great deal of
experience :-)

I have done all of this in Delphi which has even tighter restrictions on not
having circular references between units (code modules). I have designed
three main frameworks that provide all the services necessary for completely
non-circular management of business, storage and UI layers.

The frameworks are :

Value Type (not the same as ValueType :-) ) - this provides more metadata
than reflection and allows you to detect when an object goes dirtyas well as
providing validation callbacks.

Object Persistence - this is a mechanism that allows you to change
databases, even in mid-execution without changing any of your client code.
All objects are retrieved from or passed to the Persistence Broker, which
examines the ValueTypes and dynamically creates SQL, XML, CSV or whatever
you want to use for storage/retrieval/etc.

Model View Presenter - this is a very sophisticated version of MVC which
allows the management of UI interaction to be completely separated from the
business layer. It also uses the Value Types to obtain the data that it
requires to display.

There is absolutely no knowledge of the business layer in either the OPF or
MVP frameworks.

I have written several articles on these subjects; if you are interested,
they can be found on my website (I'm not very good at web design)
www.carterconsulting.org.uk. You might also find some of my writings on
Borland's Code Central.

I teach OO design more than I do anything else; and am now enjoying learning
all about Delphi Mk2 (C#) <vbg> I am also a member of Borland"s TeamB which
is their equivalent of Microsoft's MVPs.

Joanna

--
Joanna Carter
Consultant Software Engineer


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
circular referencing of formulae when setting calculation back toautomatic from manual Yuvraj Microsoft Excel Programming 2 17th Apr 2009 04:00 PM
Help getting around circular referencing =?Utf-8?B?RGF2ZQ==?= Microsoft Excel Misc 1 20th Dec 2004 11:43 AM
circular referencing john Microsoft Excel Worksheet Functions 8 20th Oct 2003 04:57 AM
Circular referencing Julie Microsoft Excel Misc 5 15th Oct 2003 05:10 PM
Re: recursive relationships ; self-referencing foreign keys ; circular references Marina Microsoft ADO .NET 3 3rd Sep 2003 04:18 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 07:57 PM.