如何将 Cookies 集合转换为通用列表?容易地
Posted
技术标签:
【中文标题】如何将 Cookies 集合转换为通用列表?容易地【英文标题】:How do I convert the Cookies collection to a generic list? Easily 【发布时间】:2011-02-24 18:01:34 【问题描述】:任何人都知道如何将Request.Cookies
转换为List<HttpCookie>
?以下内容不起作用,因为它引发了异常。
List<HttpCookie> lstCookies = new List<HttpCookie>(
Request.Cookies.Cast<HttpCookie>());
异常:无法将“System.String”类型的对象转换为“System.Web.HttpCookie”类型
【问题讨论】:
【参考方案1】:发生这种情况的原因是Request.Cookies
派生的NameObjectCollectionBase
类型枚举集合的键而不是值。因此,当您枚举 Request.Cookies
集合时,您将获得密钥:
public virtual IEnumerator GetEnumerator()
return new NameObjectKeysEnumerator(this);
这意味着以下将起作用:
string[] keys = Request.Cookies.Cast<string>().ToArray();
我想您可以尝试以下可能被认为丑陋但会起作用的方法:
List<HttpCookie> lstCookies = Request.Cookies.Keys.Cast<string>()
.Select(x => Request.Cookies[x]).ToList();
更新:
正如@Jon Benedicto 在 cmets 部分和在 his answer 中所指出的,使用 AllKeys
属性更为理想,因为它可以节省演员表:
List<HttpCookie> lstCookies = Request.Cookies.AllKeys
.Select(x => Request.Cookies[x]).ToList();
【讨论】:
但是你失去了键 -> 值连接:) @Snake,我同意你的观点,从性能的角度来看这不是最佳的,因为它会多次枚举集合,但如果你有几个元素,它可能不会引人注目。 使用 HttpCookieCollection 的 AllKeys 成员可以节省演员表。请参阅我的代码答案。 这帮助我解决了 XmlSerializer 序列化键而不是值的问题。我的 NameObjectCollectionBase 子类需要将 GetEnumerator 覆盖为return this.BaseGetValues().GetEnumerator();
【参考方案2】:
如果你真的想要一个没有 key->value 连接的直接List<HttpCookie>
,那么你可以使用 LINQ 中的 Select 来做到这一点:
var cookies = Request.Cookies.AllKeys.Select(x => Request.Cookies[x]).ToList();
【讨论】:
如果 cookie 是在不同的域中创建的,IE 可以发送多个具有相同名称的 cookie。如果发生这种情况,那么上面的代码会丢失其中一个 cookie。 代码只获取第一个同名cookie。【参考方案3】:.Cookies.Cast<HttpCookie>();
尝试将键集合转换为 cookie 集合。所以你得到一个错误是正常的:)
这是一个名称 -> 值集合,因此转换为列表并不好。
我会尝试将其转换为字典。
例如:
由于 Cookies 继承自 NameObjectCollectionBase,您可以GetAllKeys(),并使用该列表获取所有值并将它们放入字典中。
例如:
Dictionary cookieCollection = new Dictionary<string, object>();
foreach(var key in Request.Cookies.GetAllKeys())
cookieCollection.Add(key, Request.Cookies.Item[key]);
【讨论】:
【参考方案4】:这个问题可能有点老了,但这里的答案并不涵盖所有情况,因为正如@C.M.所指出的那样。可以有多个同名的 cookie。
所以最简单的方法是使用 for 循环来循环 cookie 集合:
var existingCookies = new List<HttpCookie>();
for (var i = 0; i < _httpContext.Request.Cookies.Count; i++)
existingCookies.Add(_httpContext.Request.Cookies[i]);
【讨论】:
【参考方案5】:您可以通过使用集合的 Count
和 Enumerable.Range
来避免迭代键。
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Foo
public static class WebHttpExtensions
public static IEnumerable<HttpCookie> AsEnumerable(this HttpCookieCollection webCookies) =>
Enumerable
.Range(0, webCookies.Count)
.Select(ndx => webCookies[ndx]);
public static IEnumerable<System.Net.Cookie> ToNetCookies(this HttpCookieCollection webCookies) =>
webCookies
.AsEnumerable()
.Select(x => new System.Net.Cookie(x.Name, x.Value));
【讨论】:
以上是关于如何将 Cookies 集合转换为通用列表?容易地的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 json.net 将 c# 通用列表转换为 json?