简体   繁体   中英

Realizing polymorphism with Generics in C#

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. (fe 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.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM