简体   繁体   English

在C#中使用泛型实现多态

[英]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.) 我目前正在开发一个C#程序,该程序将从Excel文件中读取测量的数据,将其解析为对象,并提供将其插入数据库的可能性(我正在使用NHibernate进行此操作)。

The program will have a GUI implementation. 该程序将具有GUI实现。 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. 事实是,无论输入什么测量数据,我都只想定义一个Form类(GUI窗口)。

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. 我有两个解析器,MotorParser和SwitchboardParser,它们都有一个名为IList ParseDataTableToList(DataTable dataTable,DBConnectionWrapper dBCon)的方法 ,其中T是Motor对象或Switchboard对象。 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. 另一方面,我确实有数据库存储库,该存储库实现了方法void InsertOrUpdate(T list) ,其中T再次是Motor或Switchboard对象。 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). 好的,现在的想法是转发特定的IInsertOrUpdateList对象(MotorRepository或SwitchboardRepository)和IParser(MotorParser或SwitchboardParser)。 The earlier mentioned Form class (I called it ImportView ) should only operate with those interfaces. 前面提到的Form类(我称其为ImportView )应仅在这些接口上运行。 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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