Databuilder模式问题

时间:2015-01-05 13:16:22

标签: c# builder-pattern

我正在玩数据构建器模式,我无法理解某些行为。 我写了这个我想要实现的简化版本

    public abstract class DataBuilderParent
    {
        private MyParent myParent;

        protected void SetDataBuilder(MyParent myParent)
        {
            this.myParent = myParent;
        }

        public DataBuilderParent WithId(int id)
        {
            myParent.Id = id;
            return this;
        }
    }

    public class DataBuilderChild : DataBuilderParent
    {
        private readonly MyChild myChild = new MyChild();

        public DataBuilderChild()
        {
            base.SetDataBuilder(myChild);
        }

        public DataBuilderChild WithDescription(string description)
        {
            myChild.Description = description;
            return this;
        }

        private MyChild Build()
        {
            return myChild;
        }

        public static implicit operator MyChild(DataBuilderChild dataBuilder)
        {
            return dataBuilder.Build();
        }
    }

    public class MyParent
    {
        public int Id { get; set; }
    }

    public class MyChild : MyParent
    {
        public string Description { get; set; }
    }

使用上面的代码

   internal class Program
   {
     private static void Main(string[] args)
     {
        MyChild child = new DataBuilderChild().WithDescription("");
     }
   }

现在它将为我创建一个孩子,同时intellisense表明我可以做这个新的DataBuilderChild()。WithId(1).WithDescription(“”); 但是,当我尝试构建它失败。我不明白为什么我无法访问此方法?它是公开的,并且通过智能感知可见。 有人可以解释一下如何使它工作吗? 谢谢

修改

错误消息是:错误1无法将类型'TestProgram.Program.DataBuilderParent'隐式转换为'TestProgram.Program.MyChild'C:\ Apps \ TestProgram \ Program.cs 44 29 TestProgram

2 个答案:

答案 0 :(得分:1)

WithId的返回值为DataBuilderParent,未定义方法WithDescription;这仅在派生类DataBuilderChild中定义。显然,你的目标是在类层次结构上使用一些命名构造函数,这不能用这种方式实现。

此外,DataBuilderParent未定义强制转换运算符,既不定义MyChild也不定义MyParent,而DataBuilderChild则将转换运算符定义为MyChild,在错误消息中说明。

答案 1 :(得分:1)

我刚从评论中重构了我的答案。

public class MyParent
{
    public int Id { get; set; }
}

public class MyChild : MyParent
{
    public string Description { get; set; }
}

DataBuilderParent类中的WithDescription方法设为abstract

public abstract class DataBuilderParent
{
    private MyParent myParent;

    protected void SetDataBuilder(MyParent myParent)
    {
        this.myParent = myParent;
    }

    public DataBuilderParent WithId(int id)
    {
        myParent.Id = id;
        return this;
    }

    public abstract DataBuilderParent WithDescription(string description);

    private MyChild BuildAsChild()
    {
        return myParent as MyChild;
    }

    private MyParent Build()
    {
        return myParent;
    }

    public static implicit operator MyChild(DataBuilderParent dataBuilder)
    {
        return dataBuilder.BuildAsChild();
    }

    public static implicit operator MyParent(DataBuilderParent dataBuilder)
    {
        return dataBuilder.Build();
    }
}

然后是DataBuilderChild

public class DataBuilderChild : DataBuilderParent
{
    private readonly MyChild myChild = new MyChild();

    public DataBuilderChild()
    {
        base.SetDataBuilder(myChild);
    }

    public override DataBuilderParent WithDescription(string description)
    {
        myChild.Description = description;
        return this;
    }

    private MyChild Build()
    {
        return myChild;
    }

    public static implicit operator MyChild(DataBuilderChild dataBuilder)
    {
        return dataBuilder.Build();
    }
}

然后你会像这样构建

class Program
{
    static void Main(string[] args)
    {
        var childBuilder = new DataBuilderChild().WithId(1).WithDescription("Child");

        MyParent parent = childBuilder;

        MyChild child = childBuilder;

        Console.WriteLine(@"Parent With Id {0}", parent.Id);

        Console.WriteLine(@"Child With Id {0} and Desciprtion - {1}", child.Id, child.Description);

        Console.ReadKey();
    }
}