Click here to Skip to main content
Email Password   helpLost your password?

Catharsis - Dependency Injection

This article is the next step in Catharsis documented tutorial.  Catharsis is a web-application framework gathering best-practices, using ASP.NET MVC (preview 5), NHibernate 2.0. All needed source code you can find on    

http://www.codeplex.com/Catharsis/

Catharsis-title.png

No. Chapter No. Chapter No. Chapter

New solution  VI  CatharsisArchitecture XI  (Controller layer - undone)  

II  Home page observation VII  Entity layer XII   (UI Web layer - undone) 

III  Roles and users VIII  Data layer XIII   Tracking, PAX design pattern

IV  Localization, translations IX  (Business layer - undone)   XIV  Catharsis Dependency Injection (DI, IoC)

Enter into Catharsis, new Entity (Model layer - undone)   XV  (Code Lists - undone)     

Catharsis and Dependency Injection (DI, IoC)  

Catharsis layers are as independent as you can imagine. Upper layer does not need to reference lower layer!

For example the Data layer, which serves as the only storage handler, is used on Business tier (only on business tier). But there is NO need to put reference into business.dll to get classes from data.dll, because of Catharsis framework architecture. All layers are loosely coupled.  In this article you'll see how this works.

In fact, there are references, but for another purposes.
1) The controller project must reference the business library because of direct dependency on AOP
2) References help you with building application, all project are copied into your bin directory, and you do not have to care… This is the only reason for references.

Dependency injection (DI, IoC)  

DI Dependency injection (IoC Inversion of Control) is well described in the article by Billy McCafferty – Dependency Injection for Loose Coupling. I suggest you to read it first (because the next description is based on remarks to that solution)
There are two main approaches described. For our example, let’s talk about Controller which uses Façade. In fact it uses IFacade (IPersonFacade) - interface is the esence of DI.

public interface IPersonFacade
{
    // TODO ...
}

Constructor DI

The constructor DI is forcing you to provide the IFaçade object whenever you are asking for Controller. Whenever you are creating such a controller, you have to pass existing IFacade.

public class PersonController
{
    public PersonController(IPersonFacade facade)
    {
        // TODO ...
    }
}

Setter DI

You can create controller (there is default parameter-less constructor), but the controller will throw Exception if the IFaçade setter is not filled and any controller’s method or property (which uses IFaçade) is used.   

public class PersonController
{
    public PersonController() { } 		// parameter-less constructor
    public IPersonFacade Facade { set; }	// public could be only setter
    // TODO ...
}   

Advantages of DI

Once you understand this pattern, you will use it. The first advantage comes from the interface oriented approach. Your controller uses only methods published in interface. Your implementing object can do more, for PersonController is important only the agreement provided by IPersonFacade interface.  

If TDD (unit test driven development) comes into play, any dummy object can be passed to simulate the IFaçade behavior. In such scenario you are concerning on testing controller behavior not the IFacade

When any changes are needed ‘or intended’ in inner implementation of façade implementing object (even in production environment) you can change only .dll with façade and the rest of application (upper layers) are still working. 

Think about it for a while, you can find out many more advantages. controller and façade are independent. That’s it. Only way they do communicate is via published IPersonFacade interface!  

DI challenges in framework architecture

As good the DI approach is, it brings few issues. There is a ‘controller factory’ in the ASP.NET MVC world which handles requests based on url-routing. If user asks for http://server/Person.mvc/ the factory will create the PersonController object and let him to handle user’s request.   

The built-in (MVC) solution won’t work with both above described scenarios. PersonController needs IPersonFacade (via constructor or setter) and the default factory is not able to do that job! So how to solve it…? 

I was walking in Billy McCafferty footprints. Firstly there was the NHibernate Best Practices with ASP.NET, 1.2nd Ed.

The SharpArchitecture 0.6.3 brought DI based on Spring.NET and xml files, which were describing which 'controller' needs which 'facade' or 'dao'. 

Few months ago Billy introduced the SharpArchitecture 0.7.3 which totally changes the web-application design. It’s based only on NHibernate and ASP.NET MVC, almost nothing else is needed (Spring.NET support was removed but DI remains!). As the IoC container now serves the MVC itself.   

The only think needed is to provide your own ‘ControllerFactory’ which knows how to inject the right objects to controllers (In the SharpArchtecture it is IDao what's used in controller, separated Business tier is not used).  

SharpArchitecture will inspire a lot, and you can see how this pattern should be applied in practice.  

Weak points of constructor or setter DI  

Catharsis controller needs IFacade and IModel to exist. When you are asking factory to give you IController, 3 objects must be created (IModel, IFacade and IController). Due Catharsis architecture even 4 objects, because facade needs IDao

The factory for that reason must be very very smart. It must be able to create all these objects (somehow) to return the single controller object.

When I was working on Catharsis that kind of Dependency Injection approach started to be crucial restriction. And even if successfully implemented it was so complicated that there was frustration instead of catharsis.

I've rolled back and changed my focus on separating of concern again. There must be the way how all need objects (IFacade, IModel and even IDao) will be injected but responsibility for doing that must remain on caller! 

Controller needs IFacade. There is (must be) FacadeFactory wich can produce any IFacade object. So let the controller itself ask that factory for injection in runtime. And also it must ask ModelFacotry for IModel. And facade itself will call DaoFactory for IDao object to be injected.

The difference, the clearness, the separation of concern – enter into catharsis again...

Catharsis DI  

Next example will show you what we are talking about:

public class PersonController
{
    public PersonController()
    {
        IPersonFacade Facade = FacadeFactory.CreateFacade<IPersonFacade>();
    }
    IPersonFacade Facade { get; set; }
} 

PersonController needs the façade, it is still true. And because the controller knows which object needs it calls FacadFactory for such an object. 

There is still controller totally independent on business layer; working with IPersonFacade instead of PersonFacade

Our gain is that we have the controller which could be created by default MVC  ControllerFactory, because it does not need any type of outer Injection (nor constructor neither setter). 

But what we have gained more? We can even provide Model the same way: 

public class PersonController
{
    public PersonController()
    {
        IPersonFacade Facade = FacadeFactory.CreateFacade<IPersonFacade>();
        IPersonModel Model = ModelFactory.CreateModel<IPersonModel>();
    }
    IPersonFacade Facade { get; set; }
    IPersonModel Model { get; set; }
}

Factory pattern 

And it is still not the end! How it is possible, that we did created IFaçade in the controller, if we know it needs the IDao object to persist objects? As you expect:

public class PersonFacade
{
    public PersonFacade()
    {
        IPersonDao Dao = DaoFactory.CreateDao<IPersonDao>();
    }
    IPersonDao Dao { get; set; }
}

Yes, this approach is breaking (despite of the fact, that is years old). Any object in any layer can ask for an interface via factory. And it could be done in a chain, because we are asking for parameter-less, independent objects (no constructor, no setter)

How factory works

Every interface defined in Common layer must be provided with ConcreteTypeAttribute, which needs the implementing object full-name and .dll in the constructor:

[ConcreteType("Firm.Product.Business.People.PersonFacade, Firm.Product.Business")]
public interface IPersonFacade : IFacade<Person> { }

This attribute was introduced in Billy McCafferty - SharpArchitecture 0.7.2. Wonderful solution, thanks a lot. This information is used by factory: 

 public static class FacadeFactory
    {
        public static T CreateFacade<T>()
        {
            var attributes = typeof(T).GetCustomAttributes(typeof(ConcreteTypeAttribute), true);
            if (attributes.Length > 0 && attributes[0] is ConcreteTypeAttribute)
            {
                var facadeName = ((ConcreteTypeAttribute)attributes[0]).TypeName;
                var targetType = Type.GetType(facadeName);
                return (T)Activator.CreateInstance(targetType);
            }
            return default(T);
        }
    }

Simple. If you would like to improve performance, reflection could be reduced and type stored for the next reuse: 

public static class FacadeFactory
    {
        static readonly SortedList<string, Type> _facades = new SortedList<string, Type>();
        public static T CreateFacade<T>()
        {
            if (_facades.ContainsKey(typeof(T).FullName))
            {
                return (T)Activator.CreateInstance(_facades[typeof(T).FullName]);
            }
            var attributes = typeof(T).GetCustomAttributes(typeof(ConcreteTypeAttribute), true);
            if (attributes.Length > 0 && attributes[0] is ConcreteTypeAttribute)
            {
                var facadeName = ((ConcreteTypeAttribute)attributes[0]).TypeName;
                var targetType = Type.GetType(facadeName);
                _facades[typeof(T).FullName] = targetType;
                return (T)Activator.CreateInstance(targetType);
            }
            return default(T);
        }
    }

Final security notes

Take care about who is using your Factories. They must be provided wisely, to avoid creating very low level object on upper ones; let’s say Dao on UI – Web layer. Catharsis therefore provides the DaoFactory only on Business layer, what means that Dao objects cannot be created in controllers! They have to use the Façades instead, which will take care about business rules. 

Source code

http://www.codeplex.com/Catharsis/

Enjoy Catharsis 

History   

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralSharpArchitecture vs. Catharsis
jalchr
21:31 26 Sep '08  
Hello
First, let me express my deep congratualations of your efforts to make developing in asp.net a more reliable process. I have a question though .... You mentioned a lot the SharpArchitecture and I'd like to know from you about what you provide which they don't. And if those two frameworks are so close why not join efforts ??
As a first look, I see they have "Logging" features, and Session state handling ... which you seem to not have.

Another thing about Nhibernate as a presistant layer.... how does it handle, for example, pagination of large data?? Would it pull all data then do paging in memory? please tell me if I miss something here !!

This might be a recommendation: why don't you add "log4net" as a logging feature for your framework.

Finally, How might we help you?
GeneralRe: SharpArchitecture vs. Catharsis
Radim Köhler
22:40 26 Sep '08  
Thanks for such a rich notes.

I) I and my colleagues were working with a few compact frameworks with lot of troubles. I’ve read and studied many articles and solutions and we’ve discussed them for a plenty of hours. All good ideas in fact were calling for a new start without any historical ballast. Catharsis is the result. (And to answer why not in cooperation with SharpArchitecture : well, to be truthful, not enough courage to ask…)

II) What Catharsis differentiates among others are 1) Guidance – very powerful tool, 2) the architecture, 3) built-in functionality ready to use, just to inherit from a base class.
- Controllers provides all needed CRUD stuff
- Localization is moved to DB
- Role management is based on One selected ‘CurrentRole’
- There is built in tracking
- Built-in web controls which allows you unlimited sorting and paging on the db side!
- There is crucial Business layer with rules (reusable by e.g. batch application...)
- Everything is open, so you can add whatever you want or need (Log4Net)
- Test driven development is supported with guidance created classes (including NHibernate)
- And probably more (I cannot remember ...)
The distribution is intended to be light-weight

III) Paging is one of the things I am proud of (but possible only due to NHibernate). Every Entity you are accessing has default Action ‘List’. It means, that even if there is a 100 thousand of rows in db you are firstly navigated to List instead of Search (of course you can change it). By default user gets 20 rows (you can change it in a SearchObject settings). Paging will throw current set of 20 rows and load new one and so on!
But even more, you can resort the list while you are standing on let’s say on 6th page. The list will be resorted but you’ll be still watching the 6th page ...

IV) Finally, anything you are asking for could be provided by default distribution – If guys like you will join the team. Soon I’ll be concerning on other (paid! Smile ) project instead of the Catharsis development. I’ll be happy if development will continue…
Do send an email...

Thanks a lot for your notes and interest
Radim Köhler
GeneralRe: SharpArchitecture vs. Catharsis
jalchr
2:23 27 Sep '08  
Could you explain more about the differences... You mentioned "Architecture", "built-in functionality" ... but could you provide the Features differences... performance differences (if measured), any crucial advantage point...
Can you say that both frameworks move on parallel paths having same architecture in mind ?

I belive you mentioned cooperation, and I believe we could start here http://code.google.com/p/sharp-architecture/[^] ... or you could communicate with Billy McCafferty on this...
lets use best features in both frameworks and build on !
GeneralRe: SharpArchitecture vs. Catharsis
Radim Köhler
2:36 27 Sep '08  
Well, there's 10 articles at the moment about Catharsis and a lot information about S#arp Architecture. If you need comparison, please, go through, download source code and observe.
For example Architecture of Catharsis has separate Chapter (there is Business tier for example).
And I did my best to describe the built-in functionality in all of these articles!
Really, and I probably won't be able to give you more information.

As developer, I am glad to have Guidance for that framework at the current version (at least).
It is base for our new projects which were and are just starting...

And if it could by useful for anybody else ... great.

I'll follow provided link (And I'll be proud to cooperate with guys like Billy Smile
Radim Köhler
GeneralDI != ServiceLocator
Roger Alsing
22:37 22 Sep '08  
What you are doing here is not really dependency injection,
its more like the old service locator pattern.

if you don't inject the dependencies, its not dependency injection..


GeneralRe: DI != ServiceLocator
Radim Köhler
22:55 22 Sep '08  
Well, you're right. There is no direct injection if you are asking for an object.
From my point of view, I will rather change the name, then the above solution Smile

I would say:
- Described approach has advantages of DI (we are working with interfaces)
- Objects are not known in the design time and can be injected in runtime (factory and ConcreteTypeAttribute)
- And even something more, because responsibility for calling the right interfaces is encapsulated (you do not have to take care for two objects).

But probably you are right, It is not pure DI.

Thanks for your note anyway.
GeneralGood stuff/
Pete O'Hanlon
5:13 22 Sep '08  
This all looks to be good stuff, but I'd rather have seen one or two longer articles.

Deja View - the feeling that you've seen this post before.

My blog | My articles | MoXAML PowerToys



GeneralRe: Good stuff/
Radim Köhler
5:44 22 Sep '08  
Thanks for your notes and mainly for your suggestion! I'll try to provide more in one article next time. Thanks Pete


Last Updated 22 Sep 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010