Circular references not possible?

R

R. Raghuraman

Hi,
Isnt there anything like forward declarations to allow me to break
circular references?

Situation is as follows:

Project1: ClassFactory.vb
-- as I need to create employees and DBWrapper objects, I need to
reference Employee project and DBWrapper project

Public class classfactory

public shared function createEmp
....
End Function

public share function createDBWrapper
....
End Function

end class



Project2: Employee
Public class Employee

public function Update()
....I need to create database wrapper object here - so need to
reference ClassFactory
...ergo ----stuck - vb.net says circular reference and throws me
out.
....also cannot find a forward declaration or late binding
....what do I do?
End Function

end Class
 
J

Jeremy Todd

R. Raghuraman said:
vb.net says circular reference and throws me out.
....also cannot find a forward declaration or late binding
....what do I do?

If these two classes work closely together, why aren't they part of the
same project?

Jeremy
 
J

Jay B. Harlow [MVP - Outlook]

R. Raghuraman,
Use a Separated Interface pattern.

http://www.martinfowler.com/eaaCatalog/separatedInterface.html

Project1 would define an IEmployee interface and an IDBWrapper interface
that has all the methods that Project1 "requires". The CreateEmployee &
CreateDBWrapper functions would return types of the interface. Project1
WOULD NOT reference project2!
public shared function CreateEmployee As IEmployee
public share function CreateDBWrapper As IDBWrapper

I normally store the actual class that implements IEmployee and IDBWrapper
in the app.config (web.config) file. so that ClassFactory is able to
dynamically load the actual implementation via
System.Configuration.ConfigurationSettings, System.Type.GetType, and
System.Activator.CreateInstance. Note I normally create a custom section of
the app.config to hold the classes to dynamically load. The type is stored
in the format "namespace.class, assembly".


Project2 would have classes that implement the interfaces defined in the
first project. Project 2 WOULD reference project1!
Public class Employee
Implements IEmployee


Public class DBWrapper
Implements IDBWrapper

Optionally IEmployee and IDBWrapper could be defined in a third class
library project that only defines the Interfaces used.

Hope this helps
Jay
 
R

R. Raghuraman

Jay B. Harlow said:
R. Raghuraman,
Use a Separated Interface pattern.

http://www.martinfowler.com/eaaCatalog/separatedInterface.html

Project1 would define an IEmployee interface and an IDBWrapper interface
that has all the methods that Project1 "requires". The CreateEmployee &
CreateDBWrapper functions would return types of the interface. Project1
WOULD NOT reference project2!



I normally store the actual class that implements IEmployee and IDBWrapper
in the app.config (web.config) file. so that ClassFactory is able to
dynamically load the actual implementation via
System.Configuration.ConfigurationSettings, System.Type.GetType, and
System.Activator.CreateInstance. Note I normally create a custom section of
the app.config to hold the classes to dynamically load. The type is stored
in the format "namespace.class, assembly".


Project2 would have classes that implement the interfaces defined in the
first project. Project 2 WOULD reference project1!

Implements IEmployee


Public class DBWrapper
Implements IDBWrapper

Optionally IEmployee and IDBWrapper could be defined in a third class
library project that only defines the Interfaces used.

Hope this helps
Jay


Jay,

Thanks for the response, but that does not solve the problem (atleast
without using reflection)

You see, Project1 will still need to refer to Project2 because even
though it returns reference to the interface, it still needs to call
teh ctor of the concrete classes that are defined in Project2


public shared function createDBWrapper as IDBWrapper
---out here I'll have to write
return new DBWrapper
end function

public shared function createMessage as IMessage
--- create one of the concrete message objects based on some logic
--however to create a concrete message object, I'll need to refer to
the
--message project)
return new SomeImplementingMessageObject ' will need to refer Project
2
end function



Since I am creating a concrete object, I still need to refer to the
project that defines the concrete object.

I have not looked at the link yet - the reason I'm replying before is
that I do have all interfaces in a separate project.


I've reverted to using reflection but am not really happy about it. Do
let me know if you've come up with something

regards,
Raghu
 
J

Jay B. Harlow [MVP - Outlook]

Raghu
I've reverted to using reflection but am not really happy about it. Do
let me know if you've come up with something
As I stated use the Separated Interface pattern!

http://www.martinfowler.com/eaaCatalog/separatedInterface.html

Remember that your ClassFactory will effectively be implementing the Plugin
pattern to dynamically load types.

http://www.martinfowler.com/eaaCatalog/plugin.html

Note you may need to read the entire book "Patterns Of Enterprise
Application Architecture" by Martin Fowler from Addison-Wesley rather then
the above pages to get the full "gist" of what the above patterns are doing
for you. As the book goes into further details & examples.

http://www.martinfowler.com/books.html#eaa
Thanks for the response, but that does not solve the problem (atleast
without using reflection)
Yes! it does solve the problem & reflection is not involved per se as you
are early binding to the interface. Some may consider reflection is involved
as you are dynamically loading the class, however you are only dynamically
loading the class, you are still early binding to the interface. Hence no
reflection is involved in execution.
You see, Project1 will still need to refer to Project2 because even
though it returns reference to the interface, it still needs to call
teh ctor of the concrete classes that are defined in Project2
The Activator.CreateInstance will call the ctor of the concrete class, the
name of the concrete class will be in the app.config. You will early bind to
the interface!

' app.config file
<configuration>
<appSettings>
<add key="IDBWrapper" value="Project2.DBWrapper, Project2" />
</appSettings>
</configuration>


' various files in the ClassFactory project

Public Interface IDBWrapper
Sub Method1()
Sub Method2()
End Interface
public shared function createDBWrapper as IDBWrapper
Dim typeName As String
typeName =
Configuration.ConfigurationSettings.AppSettings("IDBWrapper")
Dim t As Type
t = Type.GetType(typeName)
Dim value As Object
value = Activator.CreateInstance(t)
Return DirectCast(value, IDBWrapper)
end function

' Then in some project that references the Class Factory Project
Option Strict On

Dim dbw As IDBWrapper
dbw = ClassFactory.CreateDBWrapper()
dbw.Method1()
dbw.Method2()

As the name Separated Interface suggests, the interface to your DBWrapper is
separated from the implementation, two major benefits include (but are not
limited to):

1. You can easily change the implementation without recompiling your app.
You could include any of the following lines you your app config & your app
is suddenly using SQL Server, Odbc, Ole DB, or Oracle as the database. (The
plug in pattern)
<add key="IDBWrapper" value="Project2.SqlDBWrapper, Project2" />
<add key="IDBWrapper" value="Project2.ObdcDBWrapper, Project2" />
<add key="IDBWrapper" value="Project2.OleDbDBWrapper, Project2" />
<add key="IDBWrapper" value="Project3.OracleDBWrapper, Project3" />

2. You can have circular references between assemblies without resorting to
Reflection or Late Binding.

The key is that your app only knows about the Interface & uses the Interface
for early binding, meanwhile back in the liar (I mean Class Factory) you use
Activator.CreateInstance to dynamically load the concrete class that offers
the implementation for the interface.

Remember that using an Interface (Public Interface MyInterface) allows you
to have Early binding while keeping the Implementation (Public Class
MyClass) hidden out of the way.

Hope this helps
Jay


R. Raghuraman said:
"Jay B. Harlow [MVP - Outlook]" <[email protected]> wrote in message
R. Raghuraman,
Use a Separated Interface pattern.

http://www.martinfowler.com/eaaCatalog/separatedInterface.html

Project1 would define an IEmployee interface and an IDBWrapper interface
that has all the methods that Project1 "requires". The CreateEmployee &
CreateDBWrapper functions would return types of the interface. Project1
WOULD NOT reference project2!



I normally store the actual class that implements IEmployee and IDBWrapper
in the app.config (web.config) file. so that ClassFactory is able to
dynamically load the actual implementation via
System.Configuration.ConfigurationSettings, System.Type.GetType, and
System.Activator.CreateInstance. Note I normally create a custom section of
the app.config to hold the classes to dynamically load. The type is stored
in the format "namespace.class, assembly".


Project2 would have classes that implement the interfaces defined in the
first project. Project 2 WOULD reference project1!

Implements IEmployee


Public class DBWrapper
Implements IDBWrapper

Optionally IEmployee and IDBWrapper could be defined in a third class
library project that only defines the Interfaces used.

Hope this helps
Jay


Jay,

Thanks for the response, but that does not solve the problem (atleast
without using reflection)

You see, Project1 will still need to refer to Project2 because even
though it returns reference to the interface, it still needs to call
teh ctor of the concrete classes that are defined in Project2


public shared function createDBWrapper as IDBWrapper
---out here I'll have to write
return new DBWrapper
end function

public shared function createMessage as IMessage
--- create one of the concrete message objects based on some logic
--however to create a concrete message object, I'll need to refer to
the
--message project)
return new SomeImplementingMessageObject ' will need to refer Project
2
end function



Since I am creating a concrete object, I still need to refer to the
project that defines the concrete object.

I have not looked at the link yet - the reason I'm replying before is
that I do have all interfaces in a separate project.


I've reverted to using reflection but am not really happy about it. Do
let me know if you've come up with something

regards,
Raghu
 
J

Jay B. Harlow [MVP - Outlook]

Raghu,
Note I normally put the IDBWrapper & Employee setting in a custom
configuration section & not appSettings, I am only using appSettings in this
example. For example a custom DictionarySectionHandler section that you
change "key" to "domainObject" and "value" to "type".

<configuration>

<configSections>
<section name="domainObjects"
type="Project1.DomainObjectSectionHandler, Project1" />
</configSections>

<appSettings>
<add key="key1" value="value1" />
</appSettings>

<domainObjects>
<add domainObject="Employee" type="Project2.Employee, Project2" />
</domainObjects>

</configuration>


See the following on how to create new sections via the configSections
section.

http://msdn.microsoft.com/library/d...de/html/cpconconfigurationsectionhandlers.asp

and:
http://msdn.microsoft.com/library/d...ref/html/gngrfconfigurationsectionsschema.asp

Also read about the System.Configuration.ConfigurationSettings class and
other classes in the System.Configuration namespace.

Hope this helps
Jay

Jay B. Harlow said:
Raghu
I've reverted to using reflection but am not really happy about it. Do
let me know if you've come up with something
As I stated use the Separated Interface pattern!

http://www.martinfowler.com/eaaCatalog/separatedInterface.html

Remember that your ClassFactory will effectively be implementing the Plugin
pattern to dynamically load types.

http://www.martinfowler.com/eaaCatalog/plugin.html

Note you may need to read the entire book "Patterns Of Enterprise
Application Architecture" by Martin Fowler from Addison-Wesley rather then
the above pages to get the full "gist" of what the above patterns are doing
for you. As the book goes into further details & examples.

http://www.martinfowler.com/books.html#eaa
Thanks for the response, but that does not solve the problem (atleast
without using reflection)
Yes! it does solve the problem & reflection is not involved per se as you
are early binding to the interface. Some may consider reflection is involved
as you are dynamically loading the class, however you are only dynamically
loading the class, you are still early binding to the interface. Hence no
reflection is involved in execution.
You see, Project1 will still need to refer to Project2 because even
though it returns reference to the interface, it still needs to call
teh ctor of the concrete classes that are defined in Project2
The Activator.CreateInstance will call the ctor of the concrete class, the
name of the concrete class will be in the app.config. You will early bind to
the interface!

' app.config file
<configuration>
<appSettings>
<add key="IDBWrapper" value="Project2.DBWrapper, Project2" />
</appSettings>
</configuration>


' various files in the ClassFactory project

Public Interface IDBWrapper
Sub Method1()
Sub Method2()
End Interface
public shared function createDBWrapper as IDBWrapper
Dim typeName As String
typeName =
Configuration.ConfigurationSettings.AppSettings("IDBWrapper")
Dim t As Type
t = Type.GetType(typeName)
Dim value As Object
value = Activator.CreateInstance(t)
Return DirectCast(value, IDBWrapper)
end function

' Then in some project that references the Class Factory Project
Option Strict On

Dim dbw As IDBWrapper
dbw = ClassFactory.CreateDBWrapper()
dbw.Method1()
dbw.Method2()

As the name Separated Interface suggests, the interface to your DBWrapper is
separated from the implementation, two major benefits include (but are not
limited to):

1. You can easily change the implementation without recompiling your app.
You could include any of the following lines you your app config & your app
is suddenly using SQL Server, Odbc, Ole DB, or Oracle as the database. (The
plug in pattern)
<add key="IDBWrapper" value="Project2.SqlDBWrapper, Project2" />
<add key="IDBWrapper" value="Project2.ObdcDBWrapper, Project2" />
<add key="IDBWrapper" value="Project2.OleDbDBWrapper, Project2" />
<add key="IDBWrapper" value="Project3.OracleDBWrapper, Project3" />

2. You can have circular references between assemblies without resorting to
Reflection or Late Binding.

The key is that your app only knows about the Interface & uses the Interface
for early binding, meanwhile back in the liar (I mean Class Factory) you use
Activator.CreateInstance to dynamically load the concrete class that offers
the implementation for the interface.

Remember that using an Interface (Public Interface MyInterface) allows you
to have Early binding while keeping the Implementation (Public Class
MyClass) hidden out of the way.

Hope this helps
Jay
 
R

R. Raghuraman

Jay,

Am staying with the solution using reflection. I do see your point
that reflection is limited to loading the type but then on it's
straight no-reflection code (and the idea does comfort me) - It was
just that initially I was queasy about using reflection.

Thought you'd be interested in some more of it...so here goes:

Idea of separating interfaces and having the rest of the app depend
only on the interfaces is the reason I've put all my interfaces in a
separate project and localized the object creation to the factory.

As you've mentioned I too wanted to keep the configuration section
separate. In addition, I will have multiple executables that need to
use the class factory so I did not want for each executable's config
file to have all the settings - even if it's a separate section.

- Also, was quite dissappointed that the System.Configuration classes
do not allow section entries to be placed in a separate file :(

So, I'm using Configuration Management application block. That allows
me to put all the configuration settings for the class factory in a
separate configuration file with the app's configuration file pointng
to the class factory's configuration file.

And coming to the book, I'm running right now to get a copy of it :)
Cheers,
Raghu
 
J

Jay B. Harlow [MVP - Outlook]

Raghu
Idea of separating interfaces and having the rest of the app depend
only on the interfaces is the reason I've put all my interfaces in a
separate project and localized the object creation to the factory.
From what you stated earlier you put all your CLASSES in a separate project
and localized the object creation to the factory. I did not see where you
used INTERFACES...

Remember that an Interface is not a Class they are both distinct constructs
in .NET. An Interface only has the definition of Members ever, while a Class
has the implementation of the members. Of course an abstract class can have
the definition of members (see the MustInherit & MustOverride keywords)...

- Also, was quite dissappointed that the System.Configuration classes
do not allow section entries to be placed in a separate file :(
Yes they do ;-) even without the Configuration Management application
block...

Look at the NameValueFileSectionHandler, which of course is labled as "not
intended to be used directly from your code", although I remember reading
one or two articles on using it, possible the links I gave.

Of course you could always create your own SectionHandler that does support
loading entries from a separate file! If you have enough apps that need the
custom section, you can always put it in the machine.config file instead of
the app.config file.

Hope this helps
Jay

R. Raghuraman said:
Jay,

Am staying with the solution using reflection. I do see your point
that reflection is limited to loading the type but then on it's
straight no-reflection code (and the idea does comfort me) - It was
just that initially I was queasy about using reflection.

Thought you'd be interested in some more of it...so here goes:

Idea of separating interfaces and having the rest of the app depend
only on the interfaces is the reason I've put all my interfaces in a
separate project and localized the object creation to the factory.

As you've mentioned I too wanted to keep the configuration section
separate. In addition, I will have multiple executables that need to
use the class factory so I did not want for each executable's config
file to have all the settings - even if it's a separate section.

- Also, was quite dissappointed that the System.Configuration classes
do not allow section entries to be placed in a separate file :(

So, I'm using Configuration Management application block. That allows
me to put all the configuration settings for the class factory in a
separate configuration file with the app's configuration file pointng
to the class factory's configuration file.

And coming to the book, I'm running right now to get a copy of it :)
Cheers,
Raghu



"Jay B. Harlow [MVP - Outlook]" <[email protected]> wrote in message
Raghu,
Note I normally put the IDBWrapper & Employee setting in a custom
configuration section & not appSettings, I am only using appSettings in this
example. For example a custom DictionarySectionHandler section that you
change "key" to "domainObject" and "value" to "type".

<configuration>

<configSections>
<section name="domainObjects"
type="Project1.DomainObjectSectionHandler, Project1" />
</configSections>

<appSettings>
<add key="key1" value="value1" />
</appSettings>

<domainObjects>
<add domainObject="Employee" type="Project2.Employee, Project2" />
</domainObjects>

</configuration>


See the following on how to create new sections via the configSections
section.

http://msdn.microsoft.com/library/d...de/html/cpconconfigurationsectionhandlers.asp

and:
http://msdn.microsoft.com/library/d...ref/html/gngrfconfigurationsectionsschema.asp

Also read about the System.Configuration.ConfigurationSettings class and
other classes in the System.Configuration namespace.

Hope this helps
Jay

bind
to DBWrapper
is your
app Project3"
/> resorting
to you
use
 

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