.comment-link {margin-left:.6em;}
Books & Articles I wrote.

Tuesday, June 27, 2006


Avoid Cyclical Dependencies

Cyclical dependencies can be a pain when you are decoupling your entity classes from the objects that build (or populate) these entity classes. Sure, you can use interfaces and a factory class and return an instance of an object that implements the specified interface. However, it is the creation of that concrete object that can be tricky.

If you add a reference to the interfaces in the entity classes and factory classes you are ok. If you intend to use the factory class only from the builder classes then again you are fine.

return new MyConcreteType();

If you intend to use the Factory classes in the original entity classes then you run into a circular dependency issue. Your factory class references the entity class so that you can create concrete instances of your objects and your entity class would then reference the factory class. There is the argument of why you wouldn't just create an instance of the type directly in the entity, but factory classes can have their uses even in such situations (maybe the selection of the concrete type isnt straightforward as it simply implements a certain interface which can be implemented by more than 1 concrate type).

In this case you can use dynamic loading and reflection to create an instance of your type, without having a physical reference to it in the factory class. Simply store the location of the assembly in a config file and at run time the factory is passed a flag indicating the assembly to load. This is done and the following code can be used to create an instance of that type.

Assembly asm = Assembly.LoadFrom(AssemblySettings.GetConfig()["MyFactory"].ToString());
System.Type t = asm.GetType();
return Activator.CreateInstance();

This will then return a new concrate instance of your object that implements the IMyType interface. Now, when you add a reference to the factory class in your entity class you won't get a circular dependency issue.

If you need to pass parameters in the construction of the object, simply pass an object array with the boxed parameters:

int someid = 12345;
return Activator.CreateInstance(t, new object[] { someid});

You should think about caching the creation though as reflection is expensive, but two factory assemblies, one for concrete creation of types and another for dynamic loading of types may be the best solution long term.

This page is powered by Blogger. Isn't yours?

Weblog Commenting and Trackback by HaloScan.com