In an unexpected move, I decided to go back and demonstrate the automatic injection of dependencies in the old Castle sample app from before. I did so because, well, not doing so I felt kind of missed the entire point of dependency injection.
Code Changes
There are a few initial changes to the source worth mentioning: I renamed the DataSourceFacility assembly to simply DataSource as I wished to avoid the ‘Facility’ word which has a different meaning altogether in the context of Castle Windsor.
As I hinted in the previous blog post I lifted the data access method from the HomeController class to a dedicated data factory consumer class (cunningly name FactoryConsumer) in the DataSource assembly. To maintain an air of civility I also defined a new interface IFactoryConsumer which the FactoryConsumer class would then implement.
using System;
using System.Collections.Generic;
namespace DataSource
{public interface IFactoryConsumer{void LoadData(ref List<DataModel.Entity> lst,NHibernate.ISession session);}}using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataModel;
namespace DataSource
{public class FactoryConsumer : DataSource.IFactoryConsumer{IDataFactory m_fac;public FactoryConsumer(IDataFactory fac) {
m_fac = fac;}#region IFactoryConsumer Membersvoid IFactoryConsumer.LoadData(ref List<Entity> lst, NHibernate.ISession session){lst.AddRange(m_fac.GetData(session));}#endregion}}In the home controller I, perhaps not so wisely, renamed the existing data access function LoadDataFromFactory to demonstrate that it loads data directly from the IDataFactory, and created a new function LoadData that gets its data from a IFactoryConsumer. Then I changed the caller to access both function, getting product data from the Factory Consumer, where Castle secretly and automatically figures out which factory to use, while still loading service data from the factory directly as before.
Config changes
To accomplish the above there had to be some changes to the configuration file. I specified that the Product Data factory has a ‘service’, which is, incidentally IDataFactory. Ahead of both factories I declared my factory consumer. As you can see, Castle cleverly figures out quite a few things on its own, like how to create my Factory Consumer with no more than two empty hands and, incidentally, a component just a line or two below in the web.config file that actually implements IDataFactory which is what it needs to call the constructor of the FactoryConsumer.
<castle><facilities><facility id="loggingfacility"type="Castle.Facilities.Logging.LoggingFacility, Castle.Facilities.Logging"loggingApi="log4net"configFile="logging.config" /></facilities><components><component id="ProductLoader"type="DataSource.FactoryConsumer, DataSource" /><component id="ProductData"type="DataSource.ProductInfoFactory, DataSource"service="DataSource.IDataFactory, DataSource"/><component id="ServiceData"type="DataSource.ServiceInfoFactory, DataSource" /></components></castle>
Output changes
When you make the above changes to the source, rebuild and ‘play’, you will notice the following changes compared to the other source:
That’s right. Nothing. Exactly the same output is produced.
So, what was the point of all this you ask? Well, as you can see, I could easily move the ‘service’ tag in the config file and have the web page display service info only. We have lifted the dependency control right out of our lap and left it in the hands of the guy/gal who owns the config file. There are so many implications of this; everything from enabling completely changing to different data sources or services on the fly, making partial upgrades, moving from staging to production environments dynamically and so on.