Как отобразить график в реальном времени на веб-странице

У меня есть метод расширения для Uri , который:

  • Принимает анонимные объекты: uri.WithQuery(new { name = "value" })
  • Принимает коллекции string/string пар (например, Dictionary`2 ).
  • Принимает коллекции string/object пар (например, RouteValueDictionary ).
  • Принимает NameValueCollection s.
  • Сортирует значения запроса по ключу, чтобы одинаковые значения выдавали равные URI.
  • Поддерживает несколько значений для каждой клавиши, сохраняя их первоначальный порядок.
  • ]

Документально подтвержденную версию можно найти здесь здесь .

Расширение:

public static Uri WithQuery(this Uri uri, object values)
{
    if (uri == null)
        throw new ArgumentNullException(nameof(uri));

    if (values != null)
    {
        var query = string.Join(
            "&", from p in ParseQueryValues(values)
                 where !string.IsNullOrWhiteSpace(p.Key)
                 let k = HttpUtility.UrlEncode(p.Key.Trim())
                 let v = HttpUtility.UrlEncode(p.Value)
                 orderby k
                 select string.IsNullOrEmpty(v) ? k : $"{k}={v}");

        if (query.Length != 0 || uri.Query.Length != 0)
            uri = new UriBuilder(uri) { Query = query }.Uri;
    }

    return uri;
}

Парсер запросов:

private static IEnumerable> ParseQueryValues(object values)
{
    // Check if a name/value collection.
    var nvc = values as NameValueCollection;
    if (nvc != null)
        return from key in nvc.AllKeys
               from val in nvc.GetValues(key)
               select new KeyValuePair(key, val);

    // Check if a string/string dictionary.
    var ssd = values as IEnumerable>;
    if (ssd != null)
        return ssd;

    // Check if a string/object dictionary.
    var sod = values as IEnumerable>;
    if (sod == null)
    {
        // Check if a non-generic dictionary.
        var ngd = values as IDictionary;
        if (ngd != null)
            sod = ngd.Cast().ToDictionary(
                p => p.Key.ToString(), p => p.Value as object);

        // Convert object properties to dictionary.
        if (sod == null)
            sod = new RouteValueDictionary(values);
    }

    // Normalize and return the values.
    return from pair in sod
           from val in pair.Value as IEnumerable
            ?? new[] { pair.Value?.ToString() }
           select new KeyValuePair(pair.Key, val);
}

Вот тесты:

var uri = new Uri("https://stackoverflow.com/yo?oldKey=oldValue");

// Test with a string/string dictionary.
var q = uri.WithQuery(new Dictionary
{
    ["k1"] = string.Empty,
    ["k2"] = null,
    ["k3"] = "v3"
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1&k2&k3=v3"));

// Test with a string/object dictionary.
q = uri.WithQuery(new Dictionary
{
    ["k1"] = "v1",
    ["k2"] = new[] { "v2a", "v2b" },
    ["k3"] = null
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2a&k2=v2b&k3"));

// Test with a name/value collection.
var nvc = new NameValueCollection()
{
    ["k1"] = string.Empty,
    ["k2"] = "v2a"
};

nvc.Add("k2", "v2b");

q = uri.WithQuery(nvc);
Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1&k2=v2a&k2=v2b"));

// Test with any dictionary.
q = uri.WithQuery(new Dictionary>
{
    [1] = new HashSet { "v1" },
    [2] = new HashSet { "v2a", "v2b" },
    [3] = null
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?1=v1&2=v2a&2=v2b&3"));

// Test with an anonymous object.
q = uri.WithQuery(new
{
    k1 = "v1",
    k2 = new[] { "v2a", "v2b" },
    k3 = new List { "v3" },
    k4 = true,
    k5 = null as Queue
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2a&k2=v2b&k3=v3&k4=True&k5"));

// Keep existing query using a name/value collection.
nvc = HttpUtility.ParseQueryString(uri.Query);
nvc.Add("newKey", "newValue");

q = uri.WithQuery(nvc);
Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?newKey=newValue&oldKey=oldValue"));

// Merge two query objects using the RouteValueDictionary.
var an1 = new { k1 = "v1" };
var an2 = new { k2 = "v2" };

q = uri.WithQuery(
    new RouteValueDictionary(an1).Concat(
        new RouteValueDictionary(an2)));

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2"));

0
задан Love 24 February 2015 в 17:25
поделиться