如何使用 C# 泛型进行泛化?

How to generalize using C# generics?

我正在尝试制作一个结构,可以将各种文件格式解析为实体类型对象,以便存储在数据库中。

我想让代码尽可能易于阅读,并使用彼此独立的其他文件格式和实体类型进行扩展。

一般来说,我有一个文件解析器,它使用一个文件和 returns一个 DTO 模型。然后这个 DTO 模型被一个转换器使用,returns 一个数据库实体对象。解析器、转换器和 DTO 模型都扩展了抽象 classes 以避免代码重复。该过程由名为 Service 的 class 执行。

代码的本质如下:

class Service
{
    public void Run()
    {
        var model = new DerivedModel<DerivedRow>();
        var parser = new DerivedParser<DerivedModel<DerivedRow>>(model);
    }
}

class DerivedModel<TRow> : AbstractModel<DerivedRow>
    where TRow : DerivedRow
{
    public override DerivedRow NewRow()
    {
        return new DerivedRow();
    }
}

abstract class AbstractModel<TRow>
{
    public abstract TRow NewRow();
}

class DerivedRow : AbstractRow
{
}

abstract class AbstractRow
{
}

class DerivedParser<TModel> : AbstractParser<TModel>
    where TModel : AbstractModel<AbstractRow>
{
    public DerivedParser(TModel model)
    {
        Model = model;
    }

    public override TModel Parse()
    {
        var row = Model.NewRow();
        return Model;
    }
}

abstract class AbstractParser<TModel>
{
    public TModel Model { get; protected set; }

    public abstract TModel Parse();
}

类型检查器抱怨服务中的这一行代码class:

var parser = new DerivedParser<DerivedModel<DerivedRow>>(model);

错误是:

Error CS0311 The type 'Sandbox.GenericTest.DerivedModel<Sandbox.GenericTest.DerivedRow>' cannot be used as type parameter 'TModel' in the generic type or method 'DerivedParser<TModel>'. There is no implicit reference conversion from 'Sandbox.GenericTest.DerivedModel<Sandbox.GenericTest.DerivedRow>' to 'Sandbox.GenericTest.AbstractModel<Sandbox.GenericTest.AbstractRow>'.

我试过将一些接口与抽象 classes 结合使用,但这只会使事情变得复杂。

有什么建议吗?我尝试用这种方式在 C# 中做的事情是否可行?

尝试传递 TModel 并且错误消失。 您需要向 AbstractParser 提及模型的类型。一旦通过,该错误就会消失。 这是代码

class Service
{
    public void Run()
    {
        var model = new DerivedModel<DerivedRow>();
        var parser = new DerivedParser<DerivedModel<DerivedRow>, DerivedRow>(model);
    }
}

class DerivedModel<TRow> : AbstractModel<DerivedRow>
    where TRow : DerivedRow
{
    public override DerivedRow NewRow()
    {
        return new DerivedRow();
    }
}

abstract class AbstractModel<TRow> where TRow : AbstractRow
{
    public abstract TRow NewRow();
}

class DerivedRow : AbstractRow
{
}

abstract class AbstractRow
{
}



class DerivedParser<TModel, TRow> : AbstractParser<TModel, TRow>
        where TModel : AbstractModel<TRow> where TRow : AbstractRow
{
    public DerivedParser(TModel model)
    {
        Model = model;
    }

    public override TModel Parse()
    {
        var row = Model.NewRow();
        return Model;
    }
}

abstract class AbstractParser<TModel, TRow> where TRow : AbstractRow
{
    public TModel Model { get; protected set; }

    public abstract TModel Parse();
}