1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //-----------------------------------------------------------------------------
4 namespace System
.ServiceModel
.Dispatcher
7 using System
.ServiceModel
.Channels
;
8 using System
.Collections
;
9 using System
.Collections
.Generic
;
10 using System
.Collections
.ObjectModel
;
11 using System
.ServiceModel
.Diagnostics
;
12 using System
.Runtime
.Serialization
;
15 internal class ActionMessageFilterTable
<TFilterData
> : IMessageFilterTable
<TFilterData
>
17 Dictionary
<MessageFilter
, TFilterData
> filters
;
18 Dictionary
<string, List
<MessageFilter
>> actions
;
19 List
<MessageFilter
> always
;
21 public ActionMessageFilterTable()
28 this.filters
= new Dictionary
<MessageFilter
, TFilterData
>();
29 this.actions
= new Dictionary
<string, List
<MessageFilter
>>();
30 this.always
= new List
<MessageFilter
>();
33 public TFilterData
this[MessageFilter filter
]
37 return this.filters
[filter
];
41 if (this.filters
.ContainsKey(filter
))
43 this.filters
[filter
] = value;
47 this.Add(filter
, value);
56 return this.filters
.Count
;
60 [DataMember(IsRequired
= true)]
65 Entry
[] entries
= new Entry
[Count
];
67 foreach (KeyValuePair
<MessageFilter
, TFilterData
> item
in filters
)
68 entries
[i
++] = new Entry(item
.Key
, item
.Value
);
76 for (int i
= 0; i
< value.Length
; ++i
)
77 Add(value[i
].filter
, value[i
].data
);
81 public bool IsReadOnly
89 public ICollection
<MessageFilter
> Keys
93 return this.filters
.Keys
;
97 public ICollection
<TFilterData
> Values
101 return this.filters
.Values
;
105 public void Add(ActionMessageFilter filter
, TFilterData data
)
109 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("filter");
112 this.filters
.Add(filter
, data
);
113 List
<MessageFilter
> filters
;
114 #pragma warning suppress 56506 // Microsoft, Actions will never be null
115 if (filter
.Actions
.Count
== 0)
117 this.always
.Add(filter
);
121 for (int i
= 0; i
< filter
.Actions
.Count
; ++i
)
123 if (!this.actions
.TryGetValue(filter
.Actions
[i
], out filters
))
125 filters
= new List
<MessageFilter
>();
126 this.actions
.Add(filter
.Actions
[i
], filters
);
133 public void Add(MessageFilter filter
, TFilterData data
)
137 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("filter");
140 Add((ActionMessageFilter
)filter
, data
);
143 public void Add(KeyValuePair
<MessageFilter
, TFilterData
> item
)
145 Add(item
.Key
, item
.Value
);
150 this.filters
.Clear();
151 this.actions
.Clear();
155 public bool Contains(KeyValuePair
<MessageFilter
, TFilterData
> item
)
157 return ((ICollection
<KeyValuePair
<MessageFilter
, TFilterData
>>)this.filters
).Contains(item
);
160 public bool ContainsKey(MessageFilter filter
)
162 return this.filters
.ContainsKey(filter
);
165 public void CopyTo(KeyValuePair
<MessageFilter
, TFilterData
>[] array
, int arrayIndex
)
167 ((ICollection
<KeyValuePair
<MessageFilter
, TFilterData
>>)this.filters
).CopyTo(array
, arrayIndex
);
170 IEnumerator IEnumerable
.GetEnumerator()
172 return this.GetEnumerator();
175 public IEnumerator
<KeyValuePair
<MessageFilter
, TFilterData
>> GetEnumerator()
177 return ((ICollection
<KeyValuePair
<MessageFilter
, TFilterData
>>)this.filters
).GetEnumerator();
180 MessageFilter
InnerMatch(Message message
)
182 string act
= message
.Headers
.Action
;
188 List
<MessageFilter
> filters
;
189 if (this.actions
.TryGetValue(act
, out filters
))
191 if (this.always
.Count
+ filters
.Count
> 1)
193 List
<MessageFilter
> tmp
= new List
<MessageFilter
>(filters
);
194 tmp
.AddRange(this.always
);
195 Collection
<MessageFilter
> matches
= new Collection
<MessageFilter
>(tmp
);
196 throw TraceUtility
.ThrowHelperError(new MultipleFilterMatchesException(SR
.GetString(SR
.FilterMultipleMatches
), null, matches
), message
);
201 if (this.always
.Count
> 1)
203 Collection
<MessageFilter
> matches
= new Collection
<MessageFilter
>(new List
<MessageFilter
>(this.always
));
204 throw TraceUtility
.ThrowHelperError(new MultipleFilterMatchesException(SR
.GetString(SR
.FilterMultipleMatches
), null, matches
), message
);
206 else if (this.always
.Count
== 1)
208 return this.always
[0];
214 void InnerMatch(Message message
, ICollection
<MessageFilter
> results
)
216 for (int i
= 0; i
< this.always
.Count
; ++i
)
218 results
.Add(this.always
[i
]);
221 string act
= message
.Headers
.Action
;
227 List
<MessageFilter
> filters
;
228 if (this.actions
.TryGetValue(act
, out filters
))
230 for (int i
= 0; i
< filters
.Count
; ++i
)
232 results
.Add(filters
[i
]);
237 void InnerMatchData(Message message
, ICollection
<TFilterData
> results
)
239 for (int i
= 0; i
< this.always
.Count
; ++i
)
241 results
.Add(this.filters
[this.always
[i
]]);
244 string act
= message
.Headers
.Action
;
250 List
<MessageFilter
> filters
;
251 if (this.actions
.TryGetValue(act
, out filters
))
253 for (int i
= 0; i
< filters
.Count
; ++i
)
255 results
.Add(this.filters
[filters
[i
]]);
260 public bool GetMatchingValue(Message message
, out TFilterData data
)
264 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("message");
267 MessageFilter f
= InnerMatch(message
);
270 data
= default(TFilterData
);
274 data
= this.filters
[f
];
278 public bool GetMatchingValue(MessageBuffer messageBuffer
, out TFilterData data
)
280 if (messageBuffer
== null)
282 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("messageBuffer");
285 MessageFilter f
= null;
286 Message msg
= messageBuffer
.CreateMessage();
298 data
= default(TFilterData
);
302 data
= this.filters
[f
];
306 public bool GetMatchingFilter(Message message
, out MessageFilter filter
)
310 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("message");
313 filter
= InnerMatch(message
);
314 return filter
!= null;
317 public bool GetMatchingFilter(MessageBuffer messageBuffer
, out MessageFilter filter
)
319 if (messageBuffer
== null)
321 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("messageBuffer");
324 Message msg
= messageBuffer
.CreateMessage();
327 filter
= InnerMatch(msg
);
328 return filter
!= null;
336 public bool GetMatchingFilters(Message message
, ICollection
<MessageFilter
> results
)
340 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("message");
345 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("results");
348 int count
= results
.Count
;
349 InnerMatch(message
, results
);
350 return count
!= results
.Count
;
353 public bool GetMatchingFilters(MessageBuffer messageBuffer
, ICollection
<MessageFilter
> results
)
355 if (messageBuffer
== null)
357 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("messageBuffer");
362 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("results");
365 Message msg
= messageBuffer
.CreateMessage();
368 int count
= results
.Count
;
369 InnerMatch(msg
, results
);
370 return count
!= results
.Count
;
378 public bool GetMatchingValues(Message message
, ICollection
<TFilterData
> results
)
382 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("message");
387 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("results");
390 int count
= results
.Count
;
391 InnerMatchData(message
, results
);
392 return count
!= results
.Count
;
395 public bool GetMatchingValues(MessageBuffer messageBuffer
, ICollection
<TFilterData
> results
)
397 if (messageBuffer
== null)
399 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("messageBuffer");
404 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("results");
407 Message msg
= messageBuffer
.CreateMessage();
410 int count
= results
.Count
;
411 InnerMatchData(msg
, results
);
412 return count
!= results
.Count
;
420 public bool Remove(ActionMessageFilter filter
)
424 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("filter");
427 if (this.filters
.Remove(filter
))
429 #pragma warning suppress 56506 // Microsoft, ActionMessageFilter.Actions can never be null
430 if (filter
.Actions
.Count
== 0)
432 this.always
.Remove(filter
);
436 List
<MessageFilter
> filters
;
437 for (int i
= 0; i
< filter
.Actions
.Count
; ++i
)
439 #pragma warning suppress 56506 // Microsoft, PreSharp generates a false error here
440 filters
= this.actions
[filter
.Actions
[i
]];
441 #pragma warning suppress 56506 // Microsoft, filters can never be null
442 if (filters
.Count
== 1)
444 this.actions
.Remove(filter
.Actions
[i
]);
448 filters
.Remove(filter
);
457 public bool Remove(MessageFilter filter
)
461 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("filter");
464 ActionMessageFilter aFilter
= filter
as ActionMessageFilter
;
467 return Remove(aFilter
);
472 public bool Remove(KeyValuePair
<MessageFilter
, TFilterData
> item
)
474 if (((ICollection
<KeyValuePair
<MessageFilter
, TFilterData
>>)this.filters
).Contains(item
))
476 return Remove(item
.Key
);
481 public bool TryGetValue(MessageFilter filter
, out TFilterData data
)
483 return this.filters
.TryGetValue(filter
, out data
);
489 [DataMember(IsRequired
= true)]
490 internal MessageFilter filter
;
492 [DataMember(IsRequired
= true)]
493 internal TFilterData data
;
495 internal Entry(MessageFilter f
, TFilterData d
)