Reputation: 283
I am currently working on a C# program which reads measured data from Excel files, parses them to objects and provides the possibility to insert them into a database (I'm using NHibernate for this btw.)
The program will have a GUI implementation. There are multiple forms of measured data. (f.e. data from a Motor or data from a Switchboard). The thing is, that I want to define only a single Form class (GUI window) regardless of what measured data comes in.
I have two parsers, MotorParser and SwitchboardParser, which both have a method called IList ParseDataTableToList(DataTable dataTable, DBConnectionWrapper dBCon) where T is either a Motor object or a Switchboard object. So, my thought was to create an interface with generics, which will be implemented by these two classes:
public interface IParser<T>
{
IList<T> ParseDataTableToList(DataTable dataTable, DBConnectionWrapper dBCon);
}
On the other hand, I do have database repositories, which implement a method void InsertOrUpdate(T list), where T, again, is either a Motor or a Switchboard object. I have also implemented an interface for this:
public interface IInsertOrUpdateList<T>
{
void InsertOrUpdate(IList<T> list);
}
Okay, the idea now is to forward both a specific IInsertOrUpdateList object (MotorRepository or SwitchboardRepository) and a IParser (MotorParser or SwitchboardParser). The earlier mentioned Form class (I called it ImportView) should only operate with those interfaces. The problem is, that I don't know whether or how this is possible when working with generics.
This is an invalid syntax of how I had the implementation in mind:
public partial class ImportView : Form
{
private IParser parser;
private IInsertOrUpdateList repository;
private dataToParse;
public ImportView(DataTable dataToParse, IParser parser, IInsertOrUpdateList repository)
{
this.parser = parser;
this.repository = repository;
this.dataToParse = dataToParse;
}
public void ParseAndInsertIntoDB()
{
repository.InsertOrUpdateList(parser.ParseDataTableToList(dataToParse, null));
}
}
When I instantiate this window, I would provide the objects which determine whether this is measured data for Motor or Switchboard objects:
ImportView = new ImportView(dataToParse, new MotorParser(), new MotorRepository());
or
ImportView = new ImportView(dataToParse, new SwitchboardParser(), new SwitchboardRepository());
Is there a way how I could realize that problem with generics or is my approach completely wrong? I'm open for any kind of ideas.
Upvotes: 1
Views: 398
Reputation: 844
It is possible to achieve this with generics as such:
First, you want to create Generic classes for your parser and repository:
public class Parser<T> : IParser<T>
{
IList<T> ParseDataTableToList(DataTable dataTable, object o)
{
var list = new List<T>();
//Your parsing logic can go:
//1) Here(using reflection, for example) or
//2) in the constructor for Motor/Switchboard object,
//in witch case they will take a reader or row object
return list;
}
}
public class Repo<T> : IInsertOrUpdateList<T>
{
void InsertOrUpdate(IList<T> list)
{
//...
}
}
And then, your Generic window class looks like this:
public partial class ImportView<T> : Form
{
private IParser<T> parser;
private IInsertOrUpdateList<T> repository;
private DataTable dataToParse;
public ImportView(DataTable dataToParse)
{
this.parser = new Parser<T>();
this.repository = new Repo<T>();
this.dataToParse = dataToParse;
}
public void ParseAndInsertIntoDB()
{
repository.InsertOrUpdate(parser.ParseDataTableToList(dataToParse, null));
}
}
And you instantiate it like this:
var ImportView = new ImportView<Motor>(YourDataTable)
Upvotes: 1