代码之家  ›  专栏  ›  技术社区  ›  Paul Alexander

通用“tthis”,用于流畅的课程

  •  11
  • Paul Alexander  · 技术社区  · 15 年前

    我正在构建一个Fluent接口,其中我有一个包含大部分Fluent逻辑的基类,以及一个添加了一些专门行为的派生类。我面临的问题是,当从派生类型的实例调用时,基类中Fluent方法的返回类型。在调用基类的方法之后,只有基类的方法可用于进一步流畅的调用。

    改变调用方法的顺序将有助于它编译,但它会降低它的可读性,这对流畅的接口来说有点意义。是否有方法为基类定义某种“this”类型,以便所有方法返回相同的类型?

    例子

    public class Field<T>
    {
        public Field<T> Name( string name )
        {
            _name = name;
            return this;
        }
    }
    
    public SpecialField<T> : Field<T>
    {
        public SpecialField<T> Special(){ return this; }
    }
    
    
    // !!! Arrgh. Special is not a member of the Field<T> class.
    var specialField = new SpecialField()
        .Name( "bing" )
        .Special();
    

    破解

    我尝试过通过如下方法来解决这个问题,但它不是有效的c:(但至少表示了我希望如何编写接口代码)。

    public class Field<T,TThis> : TThis
        where TThis : Field<T,TThis>
    {
        public TThis Name( string name ){...}
    }
    
    public SpecialField<T> : Field<T,SpecialField<T>>
    {
        public TThis Special(){ return this; }
    }
    
    1 回复  |  直到 8 年前
        1
  •  12
  •   Ryan    8 年前

    在浏览了一些其他流利的API之后,我发现了如何做到这一点。虽然不太干净,但效果很好。基本上,您为要使用的每个派生类型引入一个中间基类,它将“tthis”类型传递给实际的实现。

    样品

    public class FieldBase<T,TThis> 
        where TThis : FieldBase<T,TThis>
    {
        private string _name;
        public TThis Name( string name ) 
        {
            _name = name;
            return (TThis)this;
        }
    }
    
    public class Field<T> : FieldBase<T,Field<T>>{}
    
    public class SpecialFieldBase<T,TThis> : FieldBase<T,TThis>
        where TThis : SpecialFieldBase<T,TThis>
    {
        public TThis Special(){ return (TThis)this; }
    }
    
    public class SpecialField<T> : SpecialFieldBase<T,SpecialField<T>>{}
    
    
    // Yeah it works!
    var specialField = new SpecialField<string>()
        .Name( "bing" )
        .Special();