Separating implementation and interface: HOW?

L

Luc Kumps

(Sorry about the previous post, it got transmitted before it was complete)

We try to separate implementation and interface defintions, but we run into
a problem. I hope the guru's can solve this, as we seem to lack only a
single 'step' to have "full separation"...

We have a first project, namespace Ninterface, that contains the interface
definitions in class1_interface.cs, like this:
namespace Ninterface {
public interface IClass1{
void method1();
}
}

In a second project, namespace Nimplementation, we have an implementation of
class1 in class1.cs:
namespace Nimplementation {
public class Class1: IClass1 {
void method1() {
/** implementation of Class1.method1 **/
}
}

In any project using Class1, we include the first project in the references
and we add a "Using Ninterface". All our instance references use "IClass1",
as "Class1" is completely invisible here.

But here's the problem: how do we create a new instance of a Class1 object,
without referring to the implementation in Nimplementation? We don't want do
refer to Nimplementation, only to Ninterface. So we can't use "new
Class1();". Moreover, we want to be able to have multiple parallel
implementations of Class1, being able to construct a specific one at
runtime.

Of course, we could make a third project that contains class factories able
to generate instances of the different implementations. But then this
project would need to have the 'implementation' projects in the references
and we want to exclude any 'reference' between 'class user' and 'class
implementation'.

We would like to have all the implementations 'register' their factory in a
'central 'factory'. In C++, this is easy to accomplish: define static
instances of a factory in each file, and in the instance constructor call
the central static "RegisterClass" method. But C# doesn't initialize a
static field of a class (and therefore doesn't call the constructor) unless
you USE the class for the first time. But that's exactly what we're trying
to prevent: "using" the implementation directly!

Is there any way to execute code within a number of classes "automatically"
when the program starts up, without needing to USE all these classes? Just
like the constructors of all static objects in C++ are being called (in
random order, but we don't care about order) upon program startup? Or should
we stop dreaming because this is impossible?

Thanks in advance,

Luc Kumps
 
A

Andreas Mueller

Luc said:
(Sorry about the previous post, it got transmitted before it was complete)

We try to separate implementation and interface defintions, but we run into
a problem. I hope the guru's can solve this, as we seem to lack only a
single 'step' to have "full separation"...

We have a first project, namespace Ninterface, that contains the interface
definitions in class1_interface.cs, like this:
namespace Ninterface {
public interface IClass1{
void method1();
}
}

In a second project, namespace Nimplementation, we have an implementation of
class1 in class1.cs:
namespace Nimplementation {
public class Class1: IClass1 {
void method1() {
/** implementation of Class1.method1 **/
}
}

In any project using Class1, we include the first project in the references
and we add a "Using Ninterface". All our instance references use "IClass1",
as "Class1" is completely invisible here.

But here's the problem: how do we create a new instance of a Class1 object,
without referring to the implementation in Nimplementation? We don't want do
refer to Nimplementation, only to Ninterface. So we can't use "new
Class1();". Moreover, we want to be able to have multiple parallel
implementations of Class1, being able to construct a specific one at
runtime.

Of course, we could make a third project that contains class factories able
to generate instances of the different implementations. But then this
project would need to have the 'implementation' projects in the references
and we want to exclude any 'reference' between 'class user' and 'class
implementation'.

We would like to have all the implementations 'register' their factory in a
'central 'factory'. In C++, this is easy to accomplish: define static
instances of a factory in each file, and in the instance constructor call
the central static "RegisterClass" method. But C# doesn't initialize a
static field of a class (and therefore doesn't call the constructor) unless
you USE the class for the first time. But that's exactly what we're trying
to prevent: "using" the implementation directly!

Is there any way to execute code within a number of classes "automatically"
when the program starts up, without needing to USE all these classes? Just
like the constructors of all static objects in C++ are being called (in
random order, but we don't care about order) upon program startup? Or should
we stop dreaming because this is impossible?

Thanks in advance,

Luc Kumps

Hi Luc,

you can implement some kind of PlugIn Framework yourself or use an
Dependency Injection Container. Here are some links:

Spring: http://www.springframework.net

Here is a good example how to use it:
http://www.springframework.net/doc/reference/html/quickstarts.html

Castle/Windsor:
http://www.castleproject.org/container/index.html

Another one is pico/nano container:
http://www.picocontainer.org/

If you want to implement it yourself, you basically have to load your
assemblies dynamically and call a static entry point method or
instantiate an entry point object via reflection. In your entry point
you register your class factory as you have described it in your post.


HTH,
Andy
 
L

Luc Kumps

Andreas said:
If you want to implement it yourself, you basically have to load your
assemblies dynamically and call a static entry point method or
instantiate an entry point object via reflection. In your entry point
you register your class factory as you have described it in your post.

Thanks Andy!
I'll simply use a number of
IClassRegistration cr =
(IClassRegistration)Activator.CreateInstance(Type.GetType("Namespace.Object,
Assembly"))

calls and call a static entry point method (defined in IClassRegistration)
in the resulting instance. We only have a handfull of classes we want to
create a factory for, so this will work fine and I won't need a reference
from the calling code!

I was just hoping that it was possible to call a static entry point method
in a number of classes automagically upon program startup (just like static
C++ objects in different files). But it's not too hard to do it this way!

Thanks!

Luc K
 
W

William Stacey [C# MVP]

| I'll simply use a number of
| IClassRegistration cr =
|
(IClassRegistration)Activator.CreateInstance(Type.GetType("Namespace.Object,
| Assembly"))

That seems like an easy way to do it :) Using this method, does
"Namespace.Object" need to be unique for each one? Check that. The
assembly name makes them unique even with same namespace - right?
 
D

Dave Sexton

Hi Luc,

If you know all the concrete implementations there will be at design-time, then just use them
directly. Create a factory object and call a method named CreateIClass1, for example, supplying any
variable data required for the class factory to choose the appropriate implementation of IClass1 to
be constructed and returned.

Class registration and a plug-in framework may be major overkill here. I don't see any value in
using such a convoluted approach over coding a simple factory that can instantiate and return any
one of the predefined types in your application.
 
L

Luc Kumps

Dave said:
Class registration and a plug-in framework may be major overkill
here. I don't see any value in
using such a convoluted approach over coding a simple factory that
can instantiate and return any
one of the predefined types in your application.

I think the simple "Activator.createInstance" approach in combination with a
simple automatic factory registrator is a good compromise.
We like keeping interfaces and implementations as separated as possible.
This makes the structure clear, forces one to think about the interactions
between the different parts of the application and it prevents running into
the "circular reference" problems, as classes are never referring to each
others implementations, only to each others interfaces!

Luc K
 
D

Dave Sexton

Hi Luc,

Well I'm not really sure what you mean, but I wasn't suggesting to return a concrete implementation
from the factory method. I was suggesting that you return your IClass1 interface. This preserves
separation while using a very simple design.
 
L

Luc Kumps

To return the IClass1 interface, I need to be able to instantiate a Class1
implementation. To be able to do that, I need to add a "Reference" to the
Class1 implementation. And I don't want ANY 'reference' from the "user" part
of IClass1 to the "implementation" part...

Luc K
 
D

Dave Sexton

Hi Luc,

I'm not sure why adding a project reference is such a bad thing, but if you really want to avoid it
you can create a shim project that contains the factory. The project with the factory will
reference both the project containing the interface and the project containing the implementations.
The interface project won't have to reference anything. The implementations project would reference
the factory project.

Very strange, I must say.
 
D

Dave Sexton

Hi Luc,

Actually, I messed up the references but the original concept still works (I assumed that your
implementations project was the main assembly, but I think that's incorrect based on what you've
said)

- Factory references both implementations and interface projects
- Interface project requires no references
- Implementations project requires no references
- Main Assembly references interface and factory projects

If you know what all of the classes will be ahead of time then I don't see any value in this
approach.
 
L

Luc Kumps

William said:
(IClassRegistration)Activator.CreateInstance(Type.GetType("Namespace.Object,

That seems like an easy way to do it :) Using this method, does
"Namespace.Object" need to be unique for each one? Check that. The
assembly name makes them unique even with same namespace - right?

Now there's an idea, William!
I simply use the same class name in each namespace to 'register' the factory
(or factories) and I use Reflection to find all the namespaces that have
this class!
Here's the code for the central 'factory repository', the main program
should only call FactoryDepository.Init():
//*******************************************
public interface IFactory
{
object getInstance(Dictionary<string, string> settings);
}

public interface IFactoryRegistry
{
void registerFactory(string name, IFactory factory);
}

public class FactoryDepository: IFactoryRegistry
{
static Dictionary<string, IFactory> _allFactories = new
Dictionary<string, IFactory>();

static public void Init()
{
FactoryDepository f = new FactoryDepository();
// Get a list of all our factories
System.Reflection.Assembly[] assems =
AppDomain.CurrentDomain.GetAssemblies();
foreach (System.Reflection.Assembly a in assems)
{
string[] parts = a.FullName.Split(new char[] { ',' });
if (parts.Length > 0)
{
Type tFact=null;
try
{
tFact = Type.GetType(parts[0] + ".NamespaceFactory, " +
parts[0]);
}
catch (Exception) {
}
if (tFact != null)
{
Activator.CreateInstance(tFact, new object[] { f });
}
}
}
}
public void registerFactory(string name, IFactory factory)
{
_allFactories[name] = factory;
}
}

//*******************************************

And here's the part in an "implementation namespace":

//*******************************************

namespace Nimplementation
{ public class NamespaceFactory : IFactory
{
public object getInstance(Dictionary<string, string> settings)
{
return new BlaBla(); //This is were we need to instantiate the correct
implementation, based upon the "settings"
}
public NamespaceFactory(IFactoryRegistry registry)
{
registry.registerFactory("interfacename", this);
}
}

}
//*******************************************

Whenever a factory is needed , you simply use
_allFactories["interfacename].getInstance(...).

Luc K
 
D

Dave Sexton

Hi Luc,

Are you expecting to register any assemblies through configuration after deployment or will
third-parties be able to register assemblies through configuration after deployment?

--
Dave Sexton

Luc Kumps said:
William said:
(IClassRegistration)Activator.CreateInstance(Type.GetType("Namespace.Object,

That seems like an easy way to do it :) Using this method, does
"Namespace.Object" need to be unique for each one? Check that. The
assembly name makes them unique even with same namespace - right?

Now there's an idea, William!
I simply use the same class name in each namespace to 'register' the factory
(or factories) and I use Reflection to find all the namespaces that have
this class!
Here's the code for the central 'factory repository', the main program
should only call FactoryDepository.Init():
//*******************************************
public interface IFactory
{
object getInstance(Dictionary<string, string> settings);
}

public interface IFactoryRegistry
{
void registerFactory(string name, IFactory factory);
}

public class FactoryDepository: IFactoryRegistry
{
static Dictionary<string, IFactory> _allFactories = new
Dictionary<string, IFactory>();

static public void Init()
{
FactoryDepository f = new FactoryDepository();
// Get a list of all our factories
System.Reflection.Assembly[] assems =
AppDomain.CurrentDomain.GetAssemblies();
foreach (System.Reflection.Assembly a in assems)
{
string[] parts = a.FullName.Split(new char[] { ',' });
if (parts.Length > 0)
{
Type tFact=null;
try
{
tFact = Type.GetType(parts[0] + ".NamespaceFactory, " +
parts[0]);
}
catch (Exception) {
}
if (tFact != null)
{
Activator.CreateInstance(tFact, new object[] { f });
}
}
}
}
public void registerFactory(string name, IFactory factory)
{
_allFactories[name] = factory;
}
}

//*******************************************

And here's the part in an "implementation namespace":

//*******************************************

namespace Nimplementation
{ public class NamespaceFactory : IFactory
{
public object getInstance(Dictionary<string, string> settings)
{
return new BlaBla(); //This is were we need to instantiate the correct
implementation, based upon the "settings"
}
public NamespaceFactory(IFactoryRegistry registry)
{
registry.registerFactory("interfacename", this);
}
}

}
//*******************************************

Whenever a factory is needed , you simply use
_allFactories["interfacename].getInstance(...).

Luc K
 
L

Luc Kumps

Dave said:
- Factory references both implementations and interface projects
- Interface project requires no references
- Implementations project requires no references
- Main Assembly references interface and factory projects

The implementation projects need to interface to each other now and then,
and we don't want to have ANY references between implementation projects. So
projects should refer to each other through interfaces.

Luc K
 
L

Luc Kumps

Dave said:
Are you expecting to register any assemblies through configuration
after deployment or will
third-parties be able to register assemblies through configuration
after deployment?

Neither!
This is a development issue only.
We simply want to separate implementation and interface definitions as good
as possible...
Our Solution has several (implementation) Projects and we want the Projects
to refer *only* to the interfaces definitions (which we keep in a separate
file for each namespace, but all interface definitions reside in a single
namespace) and *never* to each other (i.e. to the actual implementations).
This keeps the projects (and the developers) well 'separated' and prevents
any problems with 'circular references'...

Of course, there are some drawbacks to this approach as well. E.g. an
interface can't define static methods or accessors...

Luc K
 
D

Dave Sexton

Hi Luc,
Neither!
This is a development issue only.
We simply want to separate implementation and interface definitions as good
as possible...

That's what I thought at first, but then I started doubting myself when you wouldn't except my very
simple solution.

If you're sure that a developmental-plugin approach is what you need then by all means just ignore
me :)
 
J

Jeff Louie

Luc.. It sound like you are coming from C++. To be clear, in C# if you
have two
objects with circular references to each other, and both objects as a
_set_
become unreachable, the two objects become eligible for garbage
collection.

If you want to create concrete objects from a fixed set of related
classes you can
use a static class factory. If you want to load related classes
discovered at
runtime you can use a type based class factory or an interface based
class
factory. Both of these approaches create an instance of the concrete
class but
return a reference of the related type.

http://www.geocities.com/jeff_louie/OOP/oop13.htm
http://www.geocities.com/jeff_louie/OOP/oop18.htm

Regards,
Jeff
 
L

Luc Kumps

Dave said:
Hi Luc,


That's what I thought at first, but then I started doubting myself
when you wouldn't except my very
simple solution.

Your simple solution was too simple for me to understand the first time
around :)

Here was our actual problem (simplified):
1. We had a "Main" project and projects B and C
2. Our "Main" project contained quite some code, including constructing an
instance of a class implemented in B
3. The implementation of project B needed constructing an instance of a
class implemented in C

We now understand that your simple solution means that "Main" in C# should
*only*:
1. Create all class factories the other Projects will ever need. In the
above example, a (interface!) reference to the factories for classes C and B
would need to be constructed in the "Main" project. Whenever a project needs
a factory for a class in another project, code needs to be added to the
"Main" project to create an interface reference to this factory.
2. All the non-factory-constructing code of "Main" should be moved to a
separate project A.
3. After instantiating the class factories needed by the other projects,
"Main" should start Project A, containing the actual "Main" code.

Given our C, C++ and Delphi background, this approach was new: we weren't
used to the need to separate [the construction of the class factory] and
[the actual use of the factory] in separate projects (in the above example
this means modifying the "Main" implementation every time we need a class
factory in some other class implementation in another project). But we can
certainly live with that minor quirk, if we get full
interface/implementation separation in return!

Thanks again for your patience!

Luc K
 
D

Dave Sexton

Hi Luc,
Here was our actual problem (simplified):
1. We had a "Main" project and projects B and C
2. Our "Main" project contained quite some code, including constructing an
instance of a class implemented in B
3. The implementation of project B needed constructing an instance of a
class implemented in C

I thought you had a circular dependency problem, whereby classes in project B reference classes in
project C and classes in project C also reference classes in project B. This circular dependency
doesn't work using project references in Visual Studio (as I'm sure you're aware :). If you define
interfaces in a third assembly, "Project I", then you won't need to have any circular project
dependencies. All classes in project B that reference classes in project C should have interfaces
for project C classes defined in project I, and all classes in project C that have references to
classes in project B should have interfaces for project B classes defined in project I. Class
factories for classes in project B and project C should be located in their own project (A, to use
the name you've given already).

Architecting a solution that doesn't require the use of reflection to construct known classes and
relationships, as described above, seems like it will be a much better approach. The plug-in
architecture is a complex solution (but if you do see value in it then it might be what you need :).

If it's not clear to you why I'm trying to avoid the plug-in approach, it's because you claim this
to be a development issue where you know what all of the interface implementations and their
relationships will be at design-time, and at runtime they will not change. Therefore, there is
absolutely no need for reflection. Also, the plug-in approach requires assembly registration, which
may be a security risk in your solution since it allows third-party developers to plug-in any code
they want that will run with the privileges of your application. To secure against this you must
sign each of your assemblies using the same strong-name and add the
StrongNameIdentityPermissionAttribute to each as well. Then make sure your private strong-name key
is stored in a very safe place. This approach doesn't prevent tampering, however. Anybody can
remove registered assemblies from the configuration causing your application to break without a
trace.

If you need to chain the construction of objects, as in your example, while accounting for circular
dependencies and you'd like to use class factories to do so then here is a solution that might work
for you. Let me know if this is still too primitive for your needs (the names here relate to the
project names used in our examples):

{Project I: Interfaces}

interface IB { }
interface IC { }

{Project B; References: I}

public class B1 : IB
{
public B1(IC c)
{
Console.WriteLine("B1 constructed with: " + c.GetType().ToString());
}
}

public class B2 : IB
{
public B2(IC c)
{
Console.WriteLine("B2 constructed with: " + c.GetType().ToString());
}
}

{Project C; References: I}

public class C1 : IC { }
public class C2 : IC { }

{Project A: Factories; References: I, B, C}

// static classes can be used in C# 2.0 only
public static class BFactory
{
public static IB Create(SomeState state)
{
// Based on SomeState choose the appropriate implementation of IB
// and the appropriate implementation for IC.
// Here, I'm simply checking for null
return (state == null)
? (IB) new B1(CFactory.Create(state))
: new B2(CFactory.Create(state));
}
}

// static classes can be used in C# 2.0 only
public static class CFactory
{
public static IC Create(SomeState state)
{
// Based on SomeState choose the appropriate implementation of IC.
// Here, I'm simply checking for null.
return (state == null) ? (IC) new C1() : new C2();
}
}

{Project Main; References: I, A}

static void Main(string[] args)
{
IB b = A.BFactory.Create(null);
IC c = A.CFactory.Create(null);

Console.WriteLine("BFactory created: " + b.GetType().ToString());
Console.WriteLine("CFactory created: " + c.GetType().ToString());

Console.ReadLine();
}

Don't forget that you'll have to add "using" directives as well, which I removed here for the sake
of simplicity. I created some skeleton projects in VS 2005 with the appropriate references and
added all of the above code. Here was my output:

B1 constructed with: C.C1
BFactory created: B.B1
CFactory created: C.C1

The key here is that the BFactory knew to call into the CFactory, and that each factory knows how to
construct the appropriate type based on some state supplied by the caller (the usual purpose of the
class factory pattern). The factories are hard-coded here, but if you needed more flexibility then
you could use abstract factories instead of static ones. No reflection required, however.

I admit that your needs are still not perfectly clear to me so please don't assume that I know this
to be the best solution for you. This solution might not be enough, or might not work exactly to
meet your requirements, but I feel that it's worth checking out before jumping into reflection,
losing type-safety at compile-time and introducing potential security risks.

--
Dave Sexton

Luc Kumps said:
Dave said:
Hi Luc,


That's what I thought at first, but then I started doubting myself
when you wouldn't except my very
simple solution.

Your simple solution was too simple for me to understand the first time
around :)

Here was our actual problem (simplified):
1. We had a "Main" project and projects B and C
2. Our "Main" project contained quite some code, including constructing an
instance of a class implemented in B
3. The implementation of project B needed constructing an instance of a
class implemented in C

We now understand that your simple solution means that "Main" in C# should
*only*:
1. Create all class factories the other Projects will ever need. In the
above example, a (interface!) reference to the factories for classes C and B
would need to be constructed in the "Main" project. Whenever a project needs
a factory for a class in another project, code needs to be added to the
"Main" project to create an interface reference to this factory.
2. All the non-factory-constructing code of "Main" should be moved to a
separate project A.
3. After instantiating the class factories needed by the other projects,
"Main" should start Project A, containing the actual "Main" code.

Given our C, C++ and Delphi background, this approach was new: we weren't
used to the need to separate [the construction of the class factory] and
[the actual use of the factory] in separate projects (in the above example
this means modifying the "Main" implementation every time we need a class
factory in some other class implementation in another project). But we can
certainly live with that minor quirk, if we get full
interface/implementation separation in return!

Thanks again for your patience!

Luc K
 
L

Luc Kumps

Dave Sexton said:
static void Main(string[] args)
{
IB b = A.BFactory.Create(null);
IC c = A.CFactory.Create(null);

Yes, this is the solution we ended up implementing: creating (in Main) the
interface references for all the factories that will ever be needed by one
of the projects. Initially, I was looking for a way to create "b" from
Project B and "c" from project C automatically at startup of the program: I
was trying to make each implementation resposible for creating a reference
to its factory...
But if that isn't possible in C#, then the above work-around will do just
fine!

Thanks for your assistance!

Luc K
 

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