0

I want to have a class "DataSaver" that stores some data in the HTTPSession. But I also want the ability to change my mind and have the factory class create an object that instead saves to a file or database.

I want to be able to create the DataSaver object like this:

IDataSaver obj = DataSaverFact.Create();

But obviously, the data sources would require different resources depending on which get instantiated(i.e. the class that saves in session will need the current HTTPSession, and the database version will need connection string, etc...)

But I don't want to have to pass anything to the creation method.

Is that even possible?

I was thinking of using Dependancy Injection with my factory classes looking like:

public interface IDataSaverFact
{
    IDataSaver Create();
}

public interface IDataSaver
{
    public void Save(Object data);
}

public SessionSaver : IDataSaver
{
    //PARAMETER REQUIRED SINCE SESSION ONLY AVAILABLE FROM CALLER DURING WEB REQUEST
    public SessionSaver(HTTPSession session)
    {
    }

    public void Save(Object data) {....}
}


public FileSaver : IDataSaver
{
    //NO PARAMETER HERE. THIS WILL JUST SAVE TO A FILE FROM CONFIG
    public FileSaver ()
    {
    }

    public void Save(Object data) {....}
}

public DataSaverFact : IDataSaverFact
{
    public IDataSaver Create()
    {
        * IS IT POSSIBLE/APPROPRIATE TO HOOK THIS UP VIA A DI FRAMEWORK? *
        return new SessionSaver(session);
    }
}

I have seen several examples, like here Is there a pattern for initializing objects created via a DI container, that seem close to what I have above, except the linked example is passing a parameter at creation time.

I don't want the creation to vary depending on the call to the factory, but I want the ability to be able to change the DataSaver at compile-time if decide to change data sources for technical reasons.

And then I would just change my factory class to be

public DataSaverFact : IDataSaverFact
{
    public IDataSaver Create()
    {
        return new FileSaver();
    }
}

*Edit, this is to be used in an MVC3 project

Community
  • 1
  • 1
getit
  • 623
  • 2
  • 8
  • 30

1 Answers1

2

If you've got an interface defined, and the type of concrete object is defined at compile time, then I don't see why you need DI at all. You could just have a config file with a value in it that the Factory used to decide which object to create.

e.g.

public DataSaverFact : IDataSaverFact
{
    public IDataSaver Create()
    {
      if config setting = "FileSaver" then
        return new FileSaver();
      else
        return new SessionSaver();
    }
}

If you want to avoid the hard-coded IF statement then you could store the type definition in the config file, and then instance up the return object using Activator.CreateInstance

DeanOC
  • 7,142
  • 6
  • 42
  • 56
  • The problem is that the SessionSaver requires the current session object. In this case, I would call the Fact.Create() method from an MVC controller class. How do I get the http session into SessionSaver? – getit Dec 07 '12 at 00:55
  • I'm sure that I'm showing my lack of ASP.Net here, but can't you use `return new SessionSaver(HttpContext.Session);` in your `DataSaverFact` class? – DeanOC Dec 07 '12 at 01:11
  • I think that will work, but I am also looking for the "right" way to do this as well as understand when to use DI. (The project I am working on already uses DI (using StructureMap) for NHibernate, but I was not the one who set it up) – getit Dec 07 '12 at 01:23
  • Unless you need the ability to pass different `HTTPSessionState` objects to your `SessionSaver` class, you don't need to pass `HttpContext.Session` into its ctr; just refer to it internally in the class. This makes the use of DI quite simple, as you can then just put whichever type name you like in the container's config as both `FileSaver` and `SessionSaver` classes have empty ctrs. – DeanOC Dec 07 '12 at 01:33
  • Thanks for the responses. For this particular case, I will probably go with your suggestion. But in a case where I would not have access to a parameter from within a DataSaver class, is what I described in the original post even close to being correct? – getit Dec 07 '12 at 01:44
  • +1 Yes. It's a fine solution. The correct syntax is `HttpContext.Current.Session`. Since you only use this in the factory method you haven't made anything tightly coupled to `HttpContext`(nothing more than the factory and one specific storage implementation). Hence the approach is still loosely coupled and easy to test. – jgauffin Dec 07 '12 at 07:18