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.
read 0 comments |
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.
read 0 comments |
Knowing
I had emailed Michael Munowitz, author of Knowing - i always email authors as having written myself in the past one great thing is knowing that right now, someone, somewhere is reading your work. I think it is important that such people reply and he did.
You can find my review here.
read 0 comments |
Steven: Many thanks for your kind words about Knowing, and I do appreciate the
review you posted on Amazon. As an author yourself, you undoubtedly understand
how gratifying it is to learn that a reader has benefited from your work.
Sincerely, Michael Munowitz
You can find my review here.
read 0 comments |