473,804 Members | 3,462 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Circular Referencing in C#

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??????
}
}
}

Nov 16 '05 #1
16 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??????
}
}
}


Nov 16 '05 #2
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??????
}
}
}


Nov 16 '05 #3
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?

Nov 16 '05 #4

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();
}

Nov 16 '05 #5
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.

Nov 16 '05 #6
"PromisedOyster " <Pr************ @hotmail.com> a écrit dans le message de
news: 11************* *********@f14g2 00...legr oups.com...
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 interdependenci es, 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
Nov 16 '05 #7
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
aj*******@yahoo .com

Nov 16 '05 #8
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.

Nov 16 '05 #9
"Bruce Wood" <br*******@cana da.com> a écrit dans le message de news:
11************* *********@c13g2 00...legr oups.com...
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
Nov 16 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
5263
by: jinal jhaveri | last post by:
Hi All, I have one question regarding circular inheritance I have 3 files 1) A.py , having module A and some other modules 2) B.py having module B and some other modules 3) C.py having module C and some other modules
2
1373
by: brm004 | last post by:
I have 2 DLLs (Class Libraries). Both defines single-ton objects - logger object (writes to logger) and application_management object (stores paths and other things, reads ini file of the application). Both needs to refer to each other -> application_management can write to a logger and logger needs to know the path of logger file. Of course, it's circular dependency problem. Please help me to solve this problem!!!!!
16
2846
by: Kiuhnm | last post by:
Is there an elegant way to deal with semi-circular definitions? Semi-circular definition: A { B }; B { *A }; Circular reference: A { *B }; B { *A }; The problems arise when there are more semi-circular definitions and
3
7277
by: JCB | last post by:
Hi, I have two C file which are referencing in a circular way. To simplify I use an example with car : Suppose I have a program for cars. I have car.c, structure car and functions prototypes of car.c are in a file car.h
12
7065
by: Frank Rizzo | last post by:
I have a circular reference between 2 classes in the same project (i.e. each class refers to the other). The app runs fine and I am seeing no issues, which kind of surprised me. Are there any issues that I am not seeing (performance wise or garbage collection wise) with circular references? Thanks.
2
1292
by: Tom | last post by:
Let's assume I have the following libraries: MainLib (DLL) MyControl (.NET user control) Now MyControl needs to call MainLib, so I have a reference to MainLib in MyControl. Let's then assume that I want to put a new form (MyNewForm) in MainLib, but this form requires MyControl (i.e. I will drop a copy if MyControl onto the MyNewForm). This would require me to put a reference to MyControl in MainLib. Now I have MainLib referencing
6
2134
by: nyhetsgrupper | last post by:
I'm trying to build a .NET application (C#) which I want to seperate into the classic UI, Business Logic and Data Access layers. I expected to seperate each layer into different projects and reference each as required, when I try to do this I run into circular referencing problems between the projects because the Data Access project references the Business object project and vice versa. The examples I have read from varous sources...
2
7768
by: marco.furlan | last post by:
Hi there, I have to write an optimized circular buffer to log events in C++. The elements are of type std::string. This should run under Linux on an ARM embedded system. I can dedicate to this circular log a preallocated block of fixed size and work in there. Can anybody indicate me an example or technique to do this ? Thanks Marco
5
3803
by: Madhur | last post by:
Hello If I define two classes in the same cs file. And in each class, I define the object of other class as a member. Can anyone explain me how .NET or its compiler will resolve this kind of reference since one class would not be compiled unless other is compiled. This is kind of a deadlock. Isnt it ?
0
10589
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10340
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10327
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10085
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9161
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7625
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5527
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5663
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4302
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.