How to use Fluent style syntactic sugar with c# property declaration

核能气质少年 提交于 2019-12-06 07:28:49

A fluent builder interface for the MailTemplate class would look something like this:

public class MailTemplateBuilder
{
    string _body;
    string _subject;
    string _sender;

    public MailTemplateBuilder WithBody(string body)
    {
        _body = body;
        return this;
    }

    public MailTemplateBuilder WithSubject(string subject)
    {
        _subject = subject;
        return this;
    }

    public MailTemplateBuilder WithSender(string sender)
    {
        _sender = sender;
        return this;
    }

    public MailTemplate Build()
    {
        return new MailTemplate(_sender, _subject, _body);
    }
}

Usage would look like this:

var template = _builder.WithBody("body")
                       .WithSubject("subject")
                       .WithSender("sender")
                       .Build();

Another approach would be to use extension methods:

public static class MailTemplateBuilder
{
    public static MailTemplate WithBody(this MailTemplate item, string body)
    {
        item.MailBody = body;
        return item;
    }

    public static MailTemplate WithSubject(this MailTemplate item, string subject)
    {
        item.MailSubject = subject;
        return item;
    }

    public static MailTemplate WithSender(this MailTemplate item, string sender)
    {
        item.MailFrom = sender;
        return item;
    }
}

Usage would now look like this:

var template = new MailTemplate().WithBody("body")
                                 .WithSubject("subject")
                                 .WithSender("sender");

Please note:
In both cases, the MailTemplate class is not polluted with code for this fluent interface. It would be a simple class:

public class MailTemplate
{
    string _mailBody = "";
    string _subject = "";
    string _mailFrom = "";

    public string MailBody
    {
        get { return _mailBody; }
        set { _mailBody = value ; }
    }

    public string Subject
    {
        get { return _subject; }
        set { _subject = value; }
    }

    public string MailFrom
    {
        get { return _mailFrom; }
        set { _mailFrom = value; }
    }
}

So, after you created that instance with any one of the provided fluent interfaces, you can simply read the values by accessing the properties:

var body = template.MailBody;

Some frameworks e.g. FluentNHibernate just pass themselves as a lambda for this:

MailTemplate
    .ConfigureWith(mt => mt.MailBody = "hello world")
    .ConfigureWith(mt => mt.MailFrom = "rdingwall@gmail.com")
    .DoSomeOtherStuff()
    .Build();

The implementation for this would be:

public class MailTemplate
{
    // regular auto properties
    public string MailFrom { get; set; }
    public string MailBody { get; set; }

    public MailTemplate ConfigureWith(Action<MailTemplate> func)
    {
        func(this);
        return this;
    }

    ...
}

You can't use properties like that to write a fluent interface - the fields are of type string but your properties all try to return a MailTemplate.

Instead of properties, make these into methods that can be chained together.

public class MailTemplate
{
    string _MailBody = "";

    public MailTemplate Body(string mailBody)
    {
        _MailBody = mailBody;
        return this;
    }

    ...
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!