OOP Question - Pattern?

S

Shaun C Farrugia

I have a multi team solution being built where teams are segmented off
into seperate projects. One project is an over all framework containing
a Broker [worries about which db to access for data] class responsible
for instantiating different subclasses of type Connector [connects to
database - db specific] - the class only contains the abstract Connector
class and the Broker.

A seperate project contains the actual subclasses of the Connector that
are database specific. Another team will work exclusivley in that
project implementing these things.

Now the Broker class needs to be able to open the subclass dynamically.
Is there a CreateObject function that lets me pass an assembly name as
a string to some create method in order to instantiate the appropriate
object? And will I have a problem with this set up because project B
[Connector Implementations] will need to reference Project A [connector
abstract] and project A will need to know about the sub classes. Am i
missing a pattern here? The reason I need to instantiate via a string
name is so that project A doesn't need references to the subclasses.

This is my first OOP project so I might be missing something obvious.
 
S

Simon Trew

Certainly I would suggest that instead of having an abstract Connector class
you could have an IConnector interface. This will help with your decoupling
because there is no abstract class which must be inherited, it allows
Project B to design its class hierarchy without referencing yours and can
implement the IConnector interface on any class it chooses.

You will need to use reflection to get at the classes to instantiate,
presumably there will be a configuration file somewhere naming the
classes/assemblies, once you have that you can use calls such as
System.Activator to create instances.

There are some issues with dynamically loading assemblies that using
interfaces also helps to ameliorate, the main thing is that type identity is
often not preserved between assemblies (i.e. two instances created by two
different assemblies may not be considered to be the same type.)

S.

The broker would not need to know about
 
N

Nicholas Paldino [.NET/C# MVP]

Shaun,

It shouldn't be a problem. As long as your main assembly loads all of
the types that are needed by the base classs, you should be fine. So, the
things that you need to make sure you load are:

- The assembly that has the type that is the base.
- The assembly that has any interfaces that the base might implement.
- The assemblies that have the types of all the parameters, return values,
and properties.

If your derived class uses a type that is in another assembly, but the
base class doesn't expose that type, then you don't have to worry about it.

So, that being said, you can load an assembly dynamically using the
static Load method on the Assembly class.

Once you have that, you can create an instance of a type using the
static CreateInstance method on the Activator class.

Hope this helps.
 
S

Shaun C Farrugia

Where do you suggest the interface reside? Project A or B?

There will be a database table that the broker will look up the object
it needs to open up using parameters it recieves from the caller.

So then it's

GetNameOfAssembly/Class to open
Load Assembly [using system..]
Instantiate Class [using reflection]
unload Assembly when done.


Simon said:
Certainly I would suggest that instead of having an abstract Connector class
you could have an IConnector interface. This will help with your decoupling
because there is no abstract class which must be inherited, it allows
Project B to design its class hierarchy without referencing yours and can
implement the IConnector interface on any class it chooses.

You will need to use reflection to get at the classes to instantiate,
presumably there will be a configuration file somewhere naming the
classes/assemblies, once you have that you can use calls such as
System.Activator to create instances.

There are some issues with dynamically loading assemblies that using
interfaces also helps to ameliorate, the main thing is that type identity is
often not preserved between assemblies (i.e. two instances created by two
different assemblies may not be considered to be the same type.)

S.

The broker would not need to know about
I have a multi team solution being built where teams are segmented off
into seperate projects. One project is an over all framework containing
a Broker [worries about which db to access for data] class responsible
for instantiating different subclasses of type Connector [connects to
database - db specific] - the class only contains the abstract Connector
class and the Broker.

A seperate project contains the actual subclasses of the Connector that
are database specific. Another team will work exclusivley in that
project implementing these things.

Now the Broker class needs to be able to open the subclass dynamically.
Is there a CreateObject function that lets me pass an assembly name as
a string to some create method in order to instantiate the appropriate
object? And will I have a problem with this set up because project B
[Connector Implementations] will need to reference Project A [connector
abstract] and project A will need to know about the sub classes. Am i
missing a pattern here? The reason I need to instantiate via a string
name is so that project A doesn't need references to the subclasses.

This is my first OOP project so I might be missing something obvious.
 
N

Nicholas Paldino [.NET/C# MVP]

Shaun,

You should place the interface in another assembly, project C and have
both assemblies reference it.

Also, the last step of the process can not be done, as you can not
unload assemblies from an app domain once you have loaded them into it. You
could create a separate app domain and access it through there, but that
might be too much overhead.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Shaun C Farrugia said:
Where do you suggest the interface reside? Project A or B?

There will be a database table that the broker will look up the object
it needs to open up using parameters it recieves from the caller.

So then it's

GetNameOfAssembly/Class to open
Load Assembly [using system..]
Instantiate Class [using reflection]
unload Assembly when done.


Simon said:
Certainly I would suggest that instead of having an abstract Connector class
you could have an IConnector interface. This will help with your decoupling
because there is no abstract class which must be inherited, it allows
Project B to design its class hierarchy without referencing yours and can
implement the IConnector interface on any class it chooses.

You will need to use reflection to get at the classes to instantiate,
presumably there will be a configuration file somewhere naming the
classes/assemblies, once you have that you can use calls such as
System.Activator to create instances.

There are some issues with dynamically loading assemblies that using
interfaces also helps to ameliorate, the main thing is that type identity is
often not preserved between assemblies (i.e. two instances created by two
different assemblies may not be considered to be the same type.)

S.

The broker would not need to know about
I have a multi team solution being built where teams are segmented off
into seperate projects. One project is an over all framework containing
a Broker [worries about which db to access for data] class responsible
for instantiating different subclasses of type Connector [connects to
database - db specific] - the class only contains the abstract Connector
class and the Broker.

A seperate project contains the actual subclasses of the Connector that
are database specific. Another team will work exclusivley in that
project implementing these things.

Now the Broker class needs to be able to open the subclass dynamically.
Is there a CreateObject function that lets me pass an assembly name as
a string to some create method in order to instantiate the appropriate
object? And will I have a problem with this set up because project B
[Connector Implementations] will need to reference Project A [connector
abstract] and project A will need to know about the sub classes. Am i
missing a pattern here? The reason I need to instantiate via a string
name is so that project A doesn't need references to the subclasses.

This is my first OOP project so I might be missing something obvious.
 
N

Nicholas Paldino [.NET/C# MVP]

Shaun,

See inline:

Shaun C Farrugia said:
Unsure about what you're saying here.

Are you calling my project a, which contains all the base classes which
are inherited from, the main assembly? Project B classes is inheriting
from these classes in Project A.

The main assembly is the assembly that has the base classes, so yes,
project A.
So projA.DLL will be loaded. ProjA has the Broker class that will call
classes in ProjB.DLL

This is projA.DLL

The base class isn't implementing anything - it being a base class. Am
i misunderstanding you here?

I am just thinking that the base class might have interface
implementations as well.
values, and properties.

You mean the implemented subclasses? Not sure of what you're referring
to here either.

What I mean is that say the Broker base class returns an object of type
X. You have to make sure that the controller for this loads not only
project A, but the assembly containing X as well.
about it.

The derived class derives from a class in ProjA.DLL. So doesn't my
class expose whatever type is needed because it has to be visible to the
outside world.

Only if it is visible to the outside world. However, when I say
"doesn't expose that type", it means that you are using it to implement
something internally, without exposing it to the outside world. So if your
derived class uses classes in System.Management.dll internally, you don't
need it in your controller.
I might have class and type confused here.

I am using class and type interchangably here.
 
S

Shaun C Farrugia

Ok project A will not have to implement IConnector at all - only project
B will implement. Project A will be instancing types in Project B which
implement IConnector. So Project A can still have the IConnector
interface right since he really doesn't care about implementing, he just
wants to instance up things of type IConnector [located in B], wahtever
they may be. Do i still need to have project C?
 
N

Nicholas Paldino [.NET/C# MVP]

Shaun,

You don't NEED it, as project B can always reference project A to get
the interface.

While it won't apply in this case, if you have a situation where project
A needs to reference project B directly, you won't be able to do it, because
it would create a circular reference between assemblies, which is
disallowed. Placing the type definitions shared between the two assemblies
in another assembly will elimate this.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Shaun C Farrugia said:
Ok project A will not have to implement IConnector at all - only project
B will implement. Project A will be instancing types in Project B which
implement IConnector. So Project A can still have the IConnector
interface right since he really doesn't care about implementing, he just
wants to instance up things of type IConnector [located in B], wahtever
they may be. Do i still need to have project C?

Shaun,

You should place the interface in another assembly, project C and have
both assemblies reference it.

Also, the last step of the process can not be done, as you can not
unload assemblies from an app domain once you have loaded them into it. You
could create a separate app domain and access it through there, but that
might be too much overhead.

Hope this helps.
 
S

Shaun C Farrugia

so just to clarify...


Project C contains Interface definition [no refs, it just gets referenced].
Project A needs to instantiate types that implement said interface [refs
C for the interface and B for the implementations OR just B]
Project B has types that actually implement the said interface [refs
project C for the definition].

Would ProjA need to reference both B and C, or is a reference to B good
enough?
 

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