C# 创建fluent api问题

C# 创建fluent api问题,c#,C#,我正在尝试创建一个流畅的api。对于我的学习,我将要删除一个简单的rest客户机 到目前为止,我得到的是: public interface IOAuthAuthentication { void AddParameter(string name, string value); } public interface IRestClient { IRestClient WithBasicAuthentication(string username, string password

我正在尝试创建一个流畅的api。对于我的学习,我将要删除一个简单的rest客户机

到目前为止,我得到的是:

public interface IOAuthAuthentication
{
    void AddParameter(string name, string value);
}

public interface IRestClient
{
    IRestClient WithBasicAuthentication(string username, string password);
    IRestClient WithNetworkAuthentication(string username, string password);
    IOAuthAuthentication WithOAuthAuthentication(Uri authorizationUrl, string clientId, string clientSecret);
}

public class RestClient : IRestClient
{
    public RestClient(Uri root)
    {
    }

    public IRestClient WithBasicAuthentication(string username, string password)
    {
        return this;
    }

    public IRestClient WithNetworkAuthentication(string username, string password)
    {
        return this;
    }

    public IOAuthAuthentication WithOAuthAuthentication(Uri authorizationUrl, string clientId, string clientSecret)
    {
        return null;
    }
}
我想象过这样使用它:

        IRestClient restClient = new RestClient(new Uri(""))
                                    .WithBasicAuthentication("", "")
                                    .WithNetworkAuthentication("", "")
                                    .WithOAuthAuthentication(new Uri(""), "", "")
                                        .AddParameter("", "");
restClient.WithOAuthAuthentication(
    oauth =>
    {
        oauth.SetEndpoint("https://www.example.com")
             .AddParameter("Param1", "CoolValue")
             .AddParameter("Param2", "CoolValue2")
             .Authenticate();
    }
)
.YourNextFluentAction();
现在,很明显,您不会有3种不同的身份验证方法,但我想这将在方法本身中处理

对于OAuth身份验证,用户可能需要添加一个自定义参数,因此我定义了一个不同的返回类型。。。但是,这有一个副作用,即您不能使用
with OAuthauthentication()
.AddParameter()
结束链

用流利的语言处理这个问题的正确方法是什么?我看过一些.net核心的东西,可能在想:

WithOAuthAuthentication("", "", "", x => x.AddParameter("", ""))
并让带有OAuthauthentication()的
返回IRestClient

那会更“流畅”吗

但是如果您必须添加一组参数,那么代码看起来就不那么酷了:

.WithOAuthAuthentication("", "", "", x =>
{
   x.AddParameter("", "")
    .AddParameter("", "")
});

这是一个相当主观的问题,因为有很多风格的fluentapi。有些甚至可以对
this
上下文进行变异,在这种情况下,您可以为OAuth使用开始/结束模式,并且在这两个方法调用之间将是自定义OAuth提供程序
this
的变异版本

如果是我,我会将您的基本方法签名修改为:

public IRestClient WithOAuthAuthentication(Action<IOAuthAuthentication> oauthHandler)
{
    oauthHandler?.Invoke(new OAuthAuthentication(this));

    return this;
}

这是一个相当主观的问题,因为有很多风格的fluentapi。有些甚至可以对
this
上下文进行变异,在这种情况下,您可以为OAuth使用开始/结束模式,并且在这两个方法调用之间将是自定义OAuth提供程序
this
的变异版本

如果是我,我会将您的基本方法签名修改为:

public IRestClient WithOAuthAuthentication(Action<IOAuthAuthentication> oauthHandler)
{
    oauthHandler?.Invoke(new OAuthAuthentication(this));

    return this;
}

对于OAuth身份验证,用户可能需要添加一个自定义参数,因此我定义了一个不同的返回类型
——我不明白您的意思。对于Fluent接口,方法的返回类型总是
this
。“你必须在这个限制范围内工作。”罗伯塔维——我的意思是。。使用OAuth身份验证,用户可能需要添加特定于该身份验证方法的内容。。。AddParameter()不适用于其他类型。。。那么把它放在RestClient中有意义吗?然后用户就可以盲目地调用该方法,甚至没有任何意义。那么,您可能希望它成为流畅调用中某个地方的新OAuth(某物)
。您可以像ASP.NET Core Identity那样做。它返回一个
ISomething
,它不是.NET核心应用程序使用的
IServiceCollection
Interface@RobertHarvey看看一些.net核心代码,似乎他们做了我的最后一个示例,他们只是让外部对象返回这个,并包含一个Action/Func lambda,如果您需要设置特定于它的东西。。。对于OAuth身份验证,用户可能需要添加一个自定义参数,因此我定义了一个不同的返回类型——我不明白您的意思。对于Fluent接口,方法的返回类型总是
this
。“你必须在这个限制范围内工作。”罗伯塔维——我的意思是。。使用OAuth身份验证,用户可能需要添加特定于该身份验证方法的内容。。。AddParameter()不适用于其他类型。。。那么把它放在RestClient中有意义吗?然后用户就可以盲目地调用该方法,甚至没有任何意义。那么,您可能希望它成为流畅调用中某个地方的新OAuth(某物)。您可以像ASP.NET Core Identity那样做。它返回一个
ISomething
,它不是.NET核心应用程序使用的
IServiceCollection
Interface@RobertHarvey看看一些.net核心代码,似乎他们做了我的最后一个示例,他们只是让外部对象返回这个,并包含一个Action/Func lambda,如果您需要设置特定于它的东西。。。这是流畅的还是更像.net核心的东西?这也被称为“Hadouken”风格,因为像这样链接它们非常类似于Lisp编码风格和它们的金字塔函数=)谢谢。。。我可能会选择操作路线,因为它在.net核心中似乎无处不在,但可能会保留uri、用户名、密码作为参数,并为可选操作添加重载,因为这可能是一种边缘情况。这也被称为“Hadouken”样式,因为像这样链接它们与Lisp编码风格非常相似,它们的金字塔函数=)谢谢。。。我可能会选择操作路径,因为它在.net核心中似乎无处不在,但可能会保留uri、用户名和密码作为参数,并为可选操作添加重载,因为这可能是一个边缘情况。