C# 这个流畅的界面可以简化吗?

C# 这个流畅的界面可以简化吗?,c#,generics,fluent-interface,C#,Generics,Fluent Interface,我正在尝试实现一个流畅的接口,让我指定一个包含列的表,其中表和列都有属性。我希望能够像这样初始化table类: var t = TableBuilder.Create() .WithName("test") .WithColumn("col1").WithType("Int32") .WithColumn("col2").WithType("String")

我正在尝试实现一个流畅的接口,让我指定一个包含列的表,其中表和列都有属性。我希望能够像这样初始化table类:

var t = TableBuilder.Create()
                    .WithName("test") 
                    .WithColumn("col1").WithType("Int32")
                    .WithColumn("col2").WithType("String")
                    .WithColumn("col3");
我想出了一个有效的解决办法。我的问题是,实施是否可以简化,还是应该采取完全不同的方法?我在类似的案例中看到了扩展方法的使用,但我不知道它们是否能帮助我,或者在这种情况下如何使用它们

以下是代码(下面有一些注释):

interface-ITable
{
ITable with name(字符串tableName);
ItableAndColumnWithColumn(字符串columnName);
}
界面图标列
{
IColumn WithType(字符串类型名称);
}
接口ITableAndColum
哪里可以:ITable
其中TColumn:IColumn
{
ItableAndColumnWithColumn(字符串columnName);
ItableAndColumwithType(字符串类型名称);
}
类表和列:ITableAndColum
{
公共ITable表{get;set;}
公共IColumn列{get;set;}
public ItableAndColumn WithColumn(字符串columnName)
{
返回表.WithColumn(columnName);
}
public ItableAndColumwithType(字符串类型名称)
{
列.WithType(类型名称);
归还这个;
}
公共重写字符串ToString()
{
返回表.ToString();
}
}
类列:IColumn
{
公共字符串ColumnName{get;set;}
公共字符串类型名{get;set;}
公共IColumn WithType(字符串类型名称)
{
TypeName=TypeName;
归还这个;
}
}
类TableBuilder:ITable
{
公共字符串表名{get;set;}
列出列;
TableBuilder(){Columns=new List();}
公共静态ITable Create(){返回新的TableBuilder();}
公共ITable WithName(字符串表名)
{
TableName=TableName;
归还这个;
}
public ItableAndColumn WithColumn(字符串columnName)
{
Column thisColumn=new Column(){ColumnName=ColumnName};
列。添加(此列);
返回新的TableAndColumn(){Table=this,Column=thisColumn};
}
公共重写字符串ToString()
{
返回TableName+“(“+string.Join(“,”,Columns.Select(c=>(c.TypeName!=null?c.TypeName+”:“)+c.ColumnName))+”;
}
}
课例
{
公共示例()
{
var t=TableBuilder.Create()
.WithName(“测试”)
.WithColumn(“col1”).WithType(“Int32”)
.WithColumn(“col2”).WithType(“字符串”)
.带列(“col3”);
var tdef=t.ToString();
}
}
有两个接口
ITable
IColumn
,分别实现了
Table
column
。它们公开特定于其类型的适当方法。第三个接口
ITableAndColumn
组合了其他接口及其实现
TableAndColumn
包含对表实例和列实例的引用。该接口公开所选的
ITable
IColumn
方法,并调用相应的实例


这种方法复杂吗?扩展方法会以任何方式简化这一点吗?

我不太喜欢制作
TableAndColumn
。在我看来,这似乎是错的。它们是不同的实体。就KendoUI流畅的风格而言,我从中汲取了一页:

TableBuilder.Create()
    .WithName("test")
    .WithColumn(c => c.WithName("col1").WithType("Int32"))
    .WithColumn(c => c.WithName("col2").WithType("String"))
    .WithColumn(c => c.WithName("col3"));
注意我们是如何通过lambda配置列的。这允许我们适当地限制
IColumn
可以公开的内容

当然,您可以将其更改为:
WithColumn(“col1”,c=>c.WithType(“Int32”))
和重载
.WithColumn(“col3”)

实施:

interface ITable
{
    ITable WithColumn(Action<IColumn> c);
    ITable WithName(string tableName);  
}

interface IColumn
{
    IColumn WithName(string columnName);
    IColumn WithType(string typeName);
}

class TableBuilder : ITable
{
    public string TableName { get; set; }
    List<Column> Columns = new List<Column>();

    public static ITable Create() { return new TableBuilder(); }

    public ITable WithName(string tableName)
    {
        TableName = tableName;
        return this;
    }

    public ITable WithColumn(Action<IColumn> c) 
    { 
        Column thisColumn = new Column();
        c(thisColumn);
        Columns.Add(thisColumn);

        return this;
    }
}

class Column : IColumn
{
    public string ColumnName { get; set; }
    public string TypeName { get; set; }

    public IColumn WithName(string columnName)
    {
        ColumnName = columnName;
        return this;
    }

    public IColumn WithType(string typeName)
    {
        TypeName = typeName;
        return this;
    }
}
interface-ITable
{
可与列(动作c)匹配;
ITable with name(字符串tableName);
}
界面图标列
{
IColumn with name(字符串columnName);
IColumn WithType(字符串类型名称);
}
类TableBuilder:ITable
{
公共字符串表名{get;set;}
列表列=新列表();
公共静态ITable Create(){返回新的TableBuilder();}
公共ITable WithName(字符串表名)
{
TableName=TableName;
归还这个;
}
公共ITable with column(操作c)
{ 
Column thisColumn=新列();
c(本栏);
列。添加(此列);
归还这个;
}
}
类列:IColumn
{
公共字符串ColumnName{get;set;}
公共字符串类型名{get;set;}
带名称的公共IColumn(字符串columnName)
{
ColumnName=ColumnName;
归还这个;
}
公共IColumn WithType(字符串类型名称)
{
TypeName=TypeName;
归还这个;
}
}

出于好奇,您为什么反对使用传统风格设计API?对这个问题的回答可能会有很大的偏见,但我的评论也是如此-作为个人偏好,我希望调用
with type
方法
and type
,这样您就得到
with column(“col1”).and type(“Int32”)
我宁愿使用实际的
类型而不是字符串来定义类型。我想让我的API更具可读性。当然,这只适用于代码的适当缩进和换行,如果链不会太长,但我可以接受这两种缩进。我知道我可以使用更简单的方法链接和构造函数初始值设定项和名称参数。但我仍然想知道一些api是如何实现我在示例代码中演示的功能的。@MikeDinescu:WithType/AndType是正确的。我记住了这一点。关于传递给该方法的实际类型,您也是对的。对于上面的代码,我想让它简单一点。这就是为什么我选择参数表作为字符串。@MikeDinescu:作为一个附带问题:在相同的意义上,你会用type rathrer和type命名,你会把它命名为ITableAndColumn.IsNullable而不是ITableAndColumn。
interface ITable
{
    ITable WithColumn(Action<IColumn> c);
    ITable WithName(string tableName);  
}

interface IColumn
{
    IColumn WithName(string columnName);
    IColumn WithType(string typeName);
}

class TableBuilder : ITable
{
    public string TableName { get; set; }
    List<Column> Columns = new List<Column>();

    public static ITable Create() { return new TableBuilder(); }

    public ITable WithName(string tableName)
    {
        TableName = tableName;
        return this;
    }

    public ITable WithColumn(Action<IColumn> c) 
    { 
        Column thisColumn = new Column();
        c(thisColumn);
        Columns.Add(thisColumn);

        return this;
    }
}

class Column : IColumn
{
    public string ColumnName { get; set; }
    public string TypeName { get; set; }

    public IColumn WithName(string columnName)
    {
        ColumnName = columnName;
        return this;
    }

    public IColumn WithType(string typeName)
    {
        TypeName = typeName;
        return this;
    }
}