Path.Combine很方便,但是.NET框架中是否有类似的URL函数?

我正在寻找这样的语法:

Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")

这将返回:

"http://MyUrl.com/Images/Image.jpg"


当前回答

组合它们并确保始终正确的一种简单方法是:

string.Format("{0}/{1}", Url1.Trim('/'), Url2);

其他回答

组合它们并确保始终正确的一种简单方法是:

string.Format("{0}/{1}", Url1.Trim('/'), Url2);

我有一个无需分配的字符串创建版本,我一直在成功地使用它。

注:

对于第一个字符串:它使用TrimEnd(分隔符)修剪分隔符,因此仅从字符串的末尾开始。对于余数:它使用Trim(分隔符)修剪分隔符-因此路径的起点和终点都是它不附加尾部斜杠/分隔符。虽然可以做一个简单的修改来增加这个能力。

希望你觉得这很有用!

/// <summary>
/// This implements an allocation-free string creation to construct the path.
/// This uses 3.5x LESS memory and is 2x faster than some alternate methods (StringBuilder, interpolation, string.Concat, etc.).
/// </summary>
/// <param name="str"></param>
/// <param name="paths"></param>
/// <returns></returns>
public static string ConcatPath(this string str, params string[] paths)
{
    const char separator = '/';
    if (str == null) throw new ArgumentNullException(nameof(str));

    var list = new List<ReadOnlyMemory<char>>();
    var first = str.AsMemory().TrimEnd(separator);

    // get length for intial string after it's trimmed
    var length = first.Length;
    list.Add(first);

    foreach (var path in paths)
    {
        var newPath = path.AsMemory().Trim(separator);
        length += newPath.Length + 1;
        list.Add(newPath);
    }

    var newString = string.Create(length, list, (chars, state) =>
    {
        // NOTE: We don't access the 'list' variable in this delegate since 
        // it would cause a closure and allocation. Instead we access the state parameter.

        // track our position within the string data we are populating
        var position = 0;

        // copy the first string data to index 0 of the Span<char>
        state[0].Span.CopyTo(chars);

        // update the position to the new length
        position += state[0].Span.Length;

        // start at index 1 when slicing
        for (var i = 1; i < state.Count; i++)
        {
            // add a separator in the current position and increment position by 1
            chars[position++] = separator;

            // copy each path string to a slice at current position
            state[i].Span.CopyTo(chars.Slice(position));

            // update the position to the new length
            position += state[i].Length;
        }
    });
    return newString;
}

基准DotNet输出:

|                Method |     Mean |    Error |   StdDev |   Median | Ratio | RatioSD |  Gen 0 | Allocated |
|---------------------- |---------:|---------:|---------:|---------:|------:|--------:|-------:|----------:|
| ConcatPathWithBuilder | 404.1 ns | 27.35 ns | 78.48 ns | 380.3 ns |  1.00 |    0.00 | 0.3347 |   1,400 B |
|            ConcatPath | 187.2 ns |  5.93 ns | 16.44 ns | 183.2 ns |  0.48 |    0.10 | 0.0956 |     400 B |

组合URL的多个部分可能有点棘手。可以使用双参数构造函数Uri(baseUri、relativeUri),也可以使用Uri.TryCreate()实用程序函数。

在任何一种情况下,您都可能会返回错误的结果,因为这些方法会不断截断第一个参数baseUri的相对部分,例如http://google.com/some/thing到http://google.com.

为了能够将多个部分合并为最终URL,可以复制以下两个函数:

    public static string Combine(params string[] parts)
    {
        if (parts == null || parts.Length == 0) return string.Empty;

        var urlBuilder = new StringBuilder();
        foreach (var part in parts)
        {
            var tempUrl = tryCreateRelativeOrAbsolute(part);
            urlBuilder.Append(tempUrl);
        }
        return VirtualPathUtility.RemoveTrailingSlash(urlBuilder.ToString());
    }

    private static string tryCreateRelativeOrAbsolute(string s)
    {
        System.Uri uri;
        System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out uri);
        string tempUrl = VirtualPathUtility.AppendTrailingSlash(uri.ToString());
        return tempUrl;
    }

完整的代码和单元测试可以在https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs

我有单元测试来涵盖三种最常见的情况:

//阅读以上所有示例,结果创建了我自己:

static string UrlCombine(params string[] items)
{
    if (items?.Any() != true)
    {
        return string.Empty;
    }

    return string.Join("/", items.Where(u => !string.IsNullOrWhiteSpace(u)).Select(u => u.Trim('/', '\\')));
}

//用法

UrlCombine("https://microsoft.com","en-us")

我发现UriBuilder在这种情况下工作得很好:

UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath);
Uri url = urlb.Uri;
return url.AbsoluteUri;

有关更多构造函数和文档,请参阅UriBuilder类-MSDN。