Конечно, есть. Вы можете легко разместить свой собственный сервер socket.io. tlaverdure / laravel-echo-server является отличным примером этого.
Уже через несколько месяцев для поддержки веб-сокетов существует пакет Laravel на основе php:
Если Вы действительно хотите использовать ReadOnlyCollection <T>, проблема - то, что конструктор ReadOnlyCollection <T> берет IList <T>, в то время как KeyCollection Словаря является только ICollection <T>.
Таким образом, если Вы хотите перенести KeyCollection в ReadOnlyCollection, необходимо будет создать адаптер (или обертка) тип, реализовывая IList <T>, перенося KeyCollection. Таким образом, это было бы похоже:
var dictionary = ...;
var readonly_keys = new ReadOnlyCollection<T> (new CollectionListWrapper<T> (dictionary.Keys)
);
Не очень изящный, хотя, тем более, что KeyCollection уже является набором только для чтения, и что Вы могли просто раздать его как ICollection <T> :)
DrJokepu заявил, что могло бы быть трудно реализовать обертку для Набора Ключей. Но в данном случае я думаю, что реализация не является столь трудной, потому что, как мы знаем, это - обертка только для чтения.
Это позволяет нам игнорировать некоторые методы, которые, в другом случае, было бы трудно реализовать.
Вот быстрая реализация обертки для Словаря. KeyCollection:
class MyListWrapper<T, TValue> : IList<T>
{
private Dictionary<T, TValue>.KeyCollection keys;
public MyListWrapper(Dictionary<T, TValue>.KeyCollection keys)
{
this.keys = keys;
}
#region IList<T> Members
public int IndexOf(T item)
{
if (item == null)
throw new ArgumentNullException();
IEnumerator<T> e = keys.GetEnumerator();
int i = 0;
while (e.MoveNext())
{
if (e.Current.Equals(item))
return i;
i++;
}
throw new Exception("Item not found!");
}
public void Insert(int index, T item)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
public T this[int index]
{
get
{
IEnumerator<T> e = keys.GetEnumerator();
if (index < 0 || index > keys.Count)
throw new IndexOutOfRangeException();
int i = 0;
while (e.MoveNext() && i != index)
{
i++;
}
return e.Current;
}
set
{
throw new NotImplementedException();
}
}
#endregion
#region ICollection<T> Members
public void Add(T item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(T item)
{
return keys.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
keys.CopyTo(array, arrayIndex);
}
public int Count
{
get { return keys.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
public bool Remove(T item)
{
throw new NotImplementedException();
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
return keys.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return keys.GetEnumerator();
}
#endregion
}
Это не могло бы быть лучшей реализацией для этих методов :) но это было только для доказательства, что это могло бы быть сделано.
Принятие Вас использует C# 3.0, и Вы имеете:
Словарь <T, S> d;
Затем
ReadOnlyCollection <T> r = новый ReadOnlyCollection <T> (d. Ключи. ToList ());
Необходимо будет также импортировать Систему. Пространство имен Linq.
К сожалению, Вы не можете к этому direcly насколько я знаю как KeyCollection<T>
не выставляет ничего, что позволило бы Вам делать это легко.
Вы могли, однако, разделить на подклассы ReadOnlyCollection<T>
так, чтобы его конструктор получил сам словарь, и переопределите соответствующие методы так, чтобы он выставил объекты Словаря, как будто они были его собственными объектами.
Это ужасно, но это сделает это
Dictionary<int,string> dict = new Dictionary<int, string>();
...
ReadOnlyCollection<int> roc = new ReadOnlyCollection<int>((new List<int>((IEnumerable<int>)dict.Keys)));