如何使用C#泛型进行推广?

时间:2018-03-15 15:17:41

标签: c# generics nested-generics

我试图建立一个可以将各种文件格式解析为实体类型对象以便存储在数据库中的结构。

我希望使代码尽可能简单地与其他文件格式和实体类型相互独立地阅读和扩展。

通常我有一个fileparser,它使用一个文件并返回一个DTO模型。然后,转换器使用此DTO模型,该转换器返回数据库实体对象。解析器,转换器和DTO模型都扩展了抽象类以避免代码重复。该过程由一个名为Service的类进行。

这是代码的本质:

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();
}

类型检查器在Service类的这一行代码中抱怨:

  

var parser = new DerivedParser&lt; DerivedModel&lt; DerivedRow&gt;&gt;(model);

错误是:

  

错误CS0311类型&#39; Sandbox.GenericTest.DerivedModel&lt; Sandbox.GenericTest.DerivedRow&gt;&#39;不能用作类型参数&#39; TModel&#39;在通用类型或方法中,DerivedParser&lt; TModel&gt;&#39;来自&#39; Sandbox.GenericTest.DerivedModel&lt; Sandbox.GenericTest.DerivedRow&gt;&#39;没有隐式参考转换。 to&#39; Sandbox.GenericTest.AbstractModel&lt; Sandbox.GenericTest.AbstractRow&gt;&#39;。

我尝试将一些接口与抽象类结合使用,但这只是复杂的事情。

有什么建议吗?是我用C#这样做甚至可以做到的?

1 个答案:

答案 0 :(得分:1)

尝试传递 TModel ,错误就消失了。 您需要提到AbstractParser的Model类型。一旦你通过那个错误消失了。 这是代码

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();
}