//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.ServiceModel.Dispatcher { using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Runtime; using System.ServiceModel.Channels; public class MessageQueryTable : IDictionary { Dictionary collectionsByType; Dictionary dictionary; public MessageQueryTable() { this.dictionary = new Dictionary(); this.collectionsByType = new Dictionary(); } public int Count { get { return this.dictionary.Count; } } public bool IsReadOnly { get { return false; } } public ICollection Keys { get { return this.dictionary.Keys; } } public ICollection Values { get { return this.dictionary.Values; } } public TItem this[MessageQuery key] { get { return this.dictionary[key]; } set { this.Add(key, value); } } [SuppressMessage(FxCop.Category.Usage, "CA2301:EmbeddableTypesInContainersRule", MessageId = "collectionsByType", Justification = "No need to support type equivalence here.")] public void Add(MessageQuery key, TItem value) { if (key == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key"); } Type queryType = key.GetType(); MessageQueryCollection collection; if (!this.collectionsByType.TryGetValue(queryType, out collection)) { collection = key.CreateMessageQueryCollection(); if (collection == null) { collection = new SequentialMessageQueryCollection(); } this.collectionsByType.Add(queryType, collection); } collection.Add(key); this.dictionary.Add(key, value); } public void Add(KeyValuePair item) { this.Add(item.Key, item.Value); } public void Clear() { this.collectionsByType.Clear(); this.dictionary.Clear(); } public bool Contains(KeyValuePair item) { return ((ICollection>) this.dictionary).Contains(item); } public bool ContainsKey(MessageQuery key) { return this.dictionary.ContainsKey(key); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { ((ICollection>) this.dictionary).CopyTo(array, arrayIndex); } public IEnumerable> Evaluate(Message message) { if (message == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message"); } return new MessageEnumerable(this, message); } public IEnumerable> Evaluate(MessageBuffer buffer) { if (buffer == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer"); } return new MessageBufferEnumerable(this, buffer); } public IEnumerator> GetEnumerator() { return ((ICollection>) this.dictionary).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } [SuppressMessage(FxCop.Category.Usage, "CA2301:EmbeddableTypesInContainersRule", MessageId = "collectionsByType", Justification = "No need to support type equivalence here.")] public bool Remove(MessageQuery key) { if (this.dictionary.Remove(key)) { MessageQueryCollection collection; Type queryType = key.GetType(); collection = this.collectionsByType[queryType]; collection.Remove(key); if (collection.Count == 0) { this.collectionsByType.Remove(queryType); } return true; } else { return false; } } public bool Remove(KeyValuePair item) { return this.Remove(item.Key); } public bool TryGetValue(MessageQuery key, out TItem value) { return this.dictionary.TryGetValue(key, out value); } class SequentialMessageQueryCollection : MessageQueryCollection { public override IEnumerable> Evaluate(Message message) { return new MessageSequentialResultEnumerable(this, message); } public override IEnumerable> Evaluate(MessageBuffer buffer) { return new MessageBufferSequentialResultEnumerable(this, buffer); } abstract class SequentialResultEnumerable : IEnumerable> { SequentialMessageQueryCollection collection; TSource source; public SequentialResultEnumerable(SequentialMessageQueryCollection collection, TSource source) { this.collection = collection; this.source = source; } SequentialMessageQueryCollection Collection { get { return this.collection; } } protected TSource Source { get { return this.source; } } public IEnumerator> GetEnumerator() { return new SequentialResultEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } protected abstract TResult Evaluate(MessageQuery query); class SequentialResultEnumerator : IEnumerator> { SequentialResultEnumerable enumerable; IEnumerator queries; public SequentialResultEnumerator(SequentialResultEnumerable enumerable) { this.enumerable = enumerable; this.queries = enumerable.Collection.GetEnumerator(); } public KeyValuePair Current { get { MessageQuery query = queries.Current; TResult result = enumerable.Evaluate(query); return new KeyValuePair(query, result); } } object IEnumerator.Current { get { return this.Current; } } public void Dispose() { } public bool MoveNext() { return this.queries.MoveNext(); } public void Reset() { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); } } } class MessageSequentialResultEnumerable : SequentialResultEnumerable { public MessageSequentialResultEnumerable( SequentialMessageQueryCollection collection, Message message) : base(collection, message) { } protected override TResult Evaluate(MessageQuery query) { return query.Evaluate(this.Source); } } class MessageBufferSequentialResultEnumerable : SequentialResultEnumerable { public MessageBufferSequentialResultEnumerable( SequentialMessageQueryCollection collection, MessageBuffer buffer) : base(collection, buffer) { } protected override TResult Evaluate(MessageQuery query) { return query.Evaluate(this.Source); } } } abstract class Enumerable : IEnumerable> { TSource source; MessageQueryTable table; public Enumerable(MessageQueryTable table, TSource source) { this.table = table; this.source = source; } protected TSource Source { get { return this.source; } } public IEnumerator> GetEnumerator() { return new Enumerator(this); } protected abstract IEnumerator> GetInnerEnumerator(MessageQueryCollection collection); IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } class Enumerator : IEnumerator> { Enumerable enumerable; IEnumerator> innerEnumerator; IEnumerator outerEnumerator; public Enumerator(Enumerable enumerable) { this.outerEnumerator = enumerable.table.collectionsByType.Values.GetEnumerator(); this.enumerable = enumerable; } public KeyValuePair Current { get { return this.innerEnumerator.Current; } } object IEnumerator.Current { get { return this.Current; } } public void Dispose() { } public bool MoveNext() { if (innerEnumerator == null || !this.innerEnumerator.MoveNext()) { if (!this.outerEnumerator.MoveNext()) { return false; } else { MessageQueryCollection collection = this.outerEnumerator.Current; this.innerEnumerator = this.enumerable.GetInnerEnumerator(collection); return this.innerEnumerator.MoveNext(); } } else { return true; } } public void Reset() { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); } } } class MessageBufferEnumerable : Enumerable { public MessageBufferEnumerable(MessageQueryTable table, MessageBuffer buffer) : base(table, buffer) { } protected override IEnumerator> GetInnerEnumerator( MessageQueryCollection collection) { return collection.Evaluate(this.Source).GetEnumerator(); } } class MessageEnumerable : Enumerable { public MessageEnumerable(MessageQueryTable table, Message message) : base(table, message) { } protected override IEnumerator> GetInnerEnumerator( MessageQueryCollection collection) { return collection.Evaluate(this.Source).GetEnumerator(); } } } }