tags:

views:

274

answers:

3

I have a Windows Forms application that currently loads a database on startup. The flow is like this:

Program.cs => Application.Run(new MainForm()); => MainForm Constructor => Open Database

So basically MainForm holds all the bits and pieces that make the application run, while Program.cs is just a stub. Currently, the name of the database that is loaded is hardcoded, and I want to add functionality to specify the name of the database to load through the command line. At the same time, I want to add the ability to do some Unit Testing or even Dependency Injection later on, so I wonder which approach is recommended?

  • Change the constructor of MainForm to accept some parameters. Then change Program.cs to read the command line and change the call to Application.Run(new MainForm()); accordingly
  • Leave Program.cs and the Signature of the constructor untouched and check the command line in the constructor of MainForm

Method one seems to be cleaner as it would allow i.e. a Test runner to create MainForm with a test database, but as I'm usually not a WinForms developer I do not know if there could be side effects of not having a default constructor on the Main Form or if there is a better approach?

+3  A: 

I think this comes down to a separation of concerns. The Program class should be concerned with application level details and the MainForm with form details. This then says to me that that Program should parse the command line and pass the names to the form.

You could still leave the default constructor on the form and either mark it private or throw an error if you execute it. Or you could still have Program.cs use the default constructor to create the form and simply inject the database name with paramters (so it's either constructor injection or parameter injection), something like

form = new MainForm();
form.DbName = "foo";
Application.Run(form);
Kevin Jones
+2  A: 

Currently, I configure a Dependency Injection Container within Program.cs and then say

Application.Run(container.GetInstance<Form>());

The application we are currently developing has about 80 different application parts. Our MainForm currently clocks in at 95 lines of code and has dependencies to an IApplicationModule (an interface whose only property is to return a "TopControl"), a MenuStripModule, a StatusBarModule and a Session object.

flq
A: 

You can create a Singleton object (or lazy initialization) for manage DB, and initialize it in any part of code:

public class DBProvider() 
{
    private static string DefaultConnectionString = "some connection string";
    private static DBProvider instance 
    public static DBProvider GetInstance() 
    {
     get 
     {
      if (instance == null) 
      {
       instance = new DBProvider(DefaultConnectionString);
      }
      return instance;
     }
    }

    public DBProvider(string Connection string) 
    {
     ...
    }


    public static void Initialize (string ConnectionString) 
    {
     instance = new DBProvider(ConnectionString);
    }
}

And you can initialize it in Program.cs or in MainForm ctor and use DBProvider.GetInstance();

Chernikov