lundi 20 janvier 2020

Is this a good usage for the builder design pattern [closed]

I've a C# WinForms application that relies heavily on sending HttpWebRequests. I've build an HttpWebRequestBuilder, and WebRequestBodyBuilder.

public class HttpWebRequestBuilder
{
    private HttpWebRequest _httpWebRequest; // The object that will be built.
    public HttpWebRequestBuilder(string url) : this(url, Constants.FirefoxUserAgent) // Use firefox user-agent by default (Constants is a static class that has FirefoxUserAgent constant).
    {
    }

    public HttpWebRequestBuilder(string url, string userAgent)
    {
        _httpWebRequest = WebRequest.CreateHttp(url); // Create an HttpWebRequest.
        _httpWebRequest.UserAgent = userAgent; // Set the user-agent.
        _httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; // Set automatic decompression. I want this value for all requests.
    }

    public HttpWebRequestBuilder WithMethod(string method) // Set the method, "GET", "POST", etc. The default is "GET".
    {
        _httpWebRequest.Method = method;
        return this;
    }

    public HttpWebRequestBuilder Accepts(string accept) // Set the "Accept" header.
    {
        _httpWebRequest.Accept = accept;
        return this;
    }

    public HttpWebRequestBuilder WithContentType(string contentType) // Set the "Content-Type" header.
    {
        _httpWebRequest.ContentType = contentType;
        return this;
    }

    public HttpWebRequestBuilder WithCookies(CookieContainer container) // Set a cookie container.
    {
        _httpWebRequest.CookieContainer = container;
        return this;
    }

    public HttpWebRequestBuilder AllowAutoRedirect(bool allow) // Set AllowAutoRedirect
    {
        _httpWebRequest.AllowAutoRedirect = allow;
        return this;
    }

    public HttpWebRequestBuilder WithReferer(string referer) // Set referer.
    {
        _httpWebRequest.Referer = referer;
        return this;
    }

    public HttpWebRequestBuilder WithCustomHeader(string name, string value) // Add a custom header.
    {
        _httpWebRequest.Headers.Add(name, value);
        return this;
    }

    public async Task<HttpWebRequestBuilder> PostAsync(WebRequestBodyBuilder bodyBuilder) // Takes an object of WebRequestBodyBuilder (which just makes a string like "param1=value1&param2=value2&...."
    {
        byte[] buffer = Encoding.UTF8.GetBytes(bodyBuilder.ToString());
        using (var reqStrm = await _httpWebRequest.GetRequestStreamAsync()) // Write the body in the request stream.
        {
            reqStrm.Write(buffer, 0, buffer.Length);
        }
        return this;
    }

    public HttpWebRequest Build() // Returns the actual HttpWebRequest
    {
        return _httpWebRequest;
    }
}
public class WebRequestBodyBuilder
{
    private StringBuilder _stringBuilder = new StringBuilder();

    public WebRequestBodyBuilder SetKeyValuePair(string key, string value)
    {
        if (string.IsNullOrWhiteSpace(key))
            throw new ArgumentException($"Argument {nameof(key)} can't be null or whitespace."); // key can't be null, but value CAN!

        if (!string.IsNullOrWhiteSpace(_stringBuilder.ToString()))
            _stringBuilder.Append("&"); // First call shouldn't add "&" in the first.
        _stringBuilder.Append($"{WebUtility.UrlEncode(key)}={WebUtility.UrlEncode(value)}");
        return this;
    }

    public override string ToString()
    {
        return _stringBuilder.ToString(); // ToString is used in the HttpWebRequestBuilder, in the PostAsync method.
    }
}

An example usage of these is like the following:

var bodyBuilder = new WebRequestBodyBuilder()
    .SetKeyValuePair("username", Account.Username)
    .SetKeyValuePair("password", Account.Password)
    .SetKeyValuePair("auth_token", _token);


HttpWebRequest req = (await (new HttpWebRequestBuilder() // The await is for PostAsync.
    .WithMethod("POST")
    .WithReferer("https://website.com/login")
    .WithCookies(_cookies)
    .Accepts("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
    .WithContentType("application/x-www-form-urlencoded")
    .AllowAutoRedirect(false).PostAsync(bodyBuilder))).Build();
// Do something with req, like await req.GetResponseAsync()

I'm just starting learning design patterns, so I want to make sure that I'm not misusing them.

Aucun commentaire:

Enregistrer un commentaire