Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Channels / ServiceChannelProxy.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.ServiceModel.Channels
6 {
7     using System.Collections;
8     using System.Collections.Specialized;
9     using System.Globalization;
10     using System.Reflection;
11     using System.Runtime;
12     using System.Runtime.Diagnostics;
13     using System.Runtime.Remoting;
14     using System.Runtime.Remoting.Messaging;
15     using System.Runtime.Remoting.Proxies;
16     using System.Security;
17     using System.ServiceModel.Description;
18     using System.ServiceModel.Diagnostics;
19     using System.ServiceModel.Dispatcher;
20     using System.Threading.Tasks;
21
22     [Fx.Tag.SecurityNote(Critical = "Accesses a variety of LinkDemanded classes/methods (especially RealProxy)." +
23         "Caller should protect access to the ServiceChannelProxy instance after construction.")]
24 #pragma warning disable 618 // have not moved to the v4 security model yet
25     [SecurityCritical(SecurityCriticalScope.Everything)]
26 #pragma warning restore 618
27     sealed class ServiceChannelProxy : RealProxy, IRemotingTypeInfo
28     {
29         const String activityIdSlotName = "E2ETrace.ActivityID";
30         Type proxiedType;
31         Type interfaceType;
32         ServiceChannel serviceChannel;
33         MbrObject objectWrapper;
34         ImmutableClientRuntime proxyRuntime;
35         MethodDataCache methodDataCache;
36
37         internal ServiceChannelProxy(Type interfaceType, Type proxiedType, MessageDirection direction, ServiceChannel serviceChannel)
38             : base(proxiedType)
39         {
40             if (!MessageDirectionHelper.IsDefined(direction))
41                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("direction"));
42
43             this.interfaceType = interfaceType;
44             this.proxiedType = proxiedType;
45             this.serviceChannel = serviceChannel;
46             this.proxyRuntime = serviceChannel.ClientRuntime.GetRuntime();
47             this.methodDataCache = new MethodDataCache();
48
49             this.objectWrapper = new MbrObject(this, proxiedType);
50         }
51
52         //Workaround is to set the activityid in remoting call's LogicalCallContext
53         static LogicalCallContext SetActivityIdInLogicalCallContext(LogicalCallContext logicalCallContext)
54         {
55             if (TraceUtility.ActivityTracing)
56             {
57                 logicalCallContext.SetData(activityIdSlotName, DiagnosticTraceBase.ActivityId);
58             }
59
60             return logicalCallContext;
61         }
62
63         IMethodReturnMessage CreateReturnMessage(object ret, object[] returnArgs, IMethodCallMessage methodCall)
64         {
65             if (returnArgs != null)
66             {
67                 return CreateReturnMessage(ret, returnArgs, returnArgs.Length, SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext), methodCall);
68             }
69             else
70             {
71                 return new SingleReturnMessage(ret, methodCall);
72             }
73         }
74
75         IMethodReturnMessage CreateReturnMessage(object ret, object[] outArgs, int outArgsCount, LogicalCallContext callCtx, IMethodCallMessage mcm)
76         {
77             return new ReturnMessage(ret, outArgs, outArgsCount, callCtx, mcm);
78         }
79
80         IMethodReturnMessage CreateReturnMessage(Exception e, IMethodCallMessage mcm)
81         {
82             return new ReturnMessage(e, mcm);
83         }
84
85         MethodData GetMethodData(IMethodCallMessage methodCall)
86         {
87             MethodBase method = methodCall.MethodBase;
88
89             MethodData methodData;
90             if (methodDataCache.TryGetMethodData(method, out methodData))
91             {
92                 return methodData;
93             }
94
95             bool canCacheMessageData;
96
97             Type declaringType = method.DeclaringType;
98             if (declaringType == typeof(object))
99             {
100                 MethodType methodType;
101                 if (methodCall.MethodBase == typeof(object).GetMethod("GetType"))
102                 {
103                     methodType = MethodType.GetType;
104                 }
105                 else
106                 {
107                     methodType = MethodType.Object;
108                 }
109                 canCacheMessageData = true;
110                 methodData = new MethodData(method, methodType);
111             }
112             else if (declaringType.IsInstanceOfType(this.serviceChannel))
113             {
114                 canCacheMessageData = true;
115                 methodData = new MethodData(method, MethodType.Channel);
116             }
117             else
118             {
119                 ProxyOperationRuntime operation = this.proxyRuntime.GetOperation(method, methodCall.Args, out canCacheMessageData);
120
121                 if (operation == null)
122                 {
123                     if (this.serviceChannel.Factory != null)
124                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SFxMethodNotSupported1, method.Name)));
125                     else
126                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SFxMethodNotSupportedOnCallback1, method.Name)));
127                 }
128
129                 MethodType methodType;
130
131                 if (operation.IsTaskCall(methodCall))
132                 {
133                     methodType = MethodType.TaskService;
134                 }
135                 else if (operation.IsSyncCall(methodCall))
136                 {
137                     methodType = MethodType.Service;
138                 }
139                 else if (operation.IsBeginCall(methodCall))
140                 {
141                     methodType = MethodType.BeginService;
142                 }
143                 else
144                 {
145                     methodType = MethodType.EndService;
146                 }
147
148                 methodData = new MethodData(method, methodType, operation);
149             }
150
151             if (canCacheMessageData)
152             {
153                 methodDataCache.SetMethodData(methodData);
154             }
155
156             return methodData;
157         }
158
159         internal ServiceChannel GetServiceChannel()
160         {
161             return this.serviceChannel;
162         }
163
164         public override IMessage Invoke(IMessage message)
165         {
166             try
167             {
168                 IMethodCallMessage methodCall = message as IMethodCallMessage;
169
170                 if (methodCall == null)
171                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxExpectedIMethodCallMessage)));
172
173                 MethodData methodData = GetMethodData(methodCall);
174
175                 switch (methodData.MethodType)
176                 {
177                     case MethodType.Service:
178                         return InvokeService(methodCall, methodData.Operation);
179                     case MethodType.BeginService:
180                         return InvokeBeginService(methodCall, methodData.Operation);
181                     case MethodType.EndService:
182                         return InvokeEndService(methodCall, methodData.Operation);
183                     case MethodType.TaskService:
184                         return InvokeTaskService(methodCall, methodData.Operation);
185                     case MethodType.Channel:
186                         return InvokeChannel(methodCall);
187                     case MethodType.GetType:
188                         return InvokeGetType(methodCall);
189                     case MethodType.Object:
190                         return InvokeObject(methodCall);
191                     default:
192                         Fx.Assert("Invalid proxy method type");
193                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid proxy method type")));
194                 }
195             }
196 #pragma warning suppress 56500 // covered by FxCOP
197             catch (Exception e)
198             {
199                 if (Fx.IsFatal(e))
200                 {
201                     throw;
202                 }
203                 return CreateReturnMessage(e, message as IMethodCallMessage);
204             }
205         }
206
207         static class TaskCreator
208         {
209             static readonly Func<ServiceChannel, ProxyOperationRuntime, object[], AsyncCallback, object, IAsyncResult> beginCallDelegate = ServiceChannel.BeginCall;
210             static readonly Hashtable createGenericTaskDelegateCache = new Hashtable(); // using Hashtable because it allows for lock-free reads
211             static readonly MethodInfo createGenericTaskMI = typeof(TaskCreator).GetMethod("CreateGenericTask", new Type[] { typeof(ServiceChannel), typeof(ProxyOperationRuntime), typeof(object[]) });
212
213             static Func<ServiceChannel, ProxyOperationRuntime, object[], Task> GetOrCreateTaskDelegate(Type taskResultType)
214             {
215                 Func<ServiceChannel, ProxyOperationRuntime, object[], Task> createTaskDelegate = createGenericTaskDelegateCache[taskResultType] as Func<ServiceChannel, ProxyOperationRuntime, object[], Task>;
216                 if (createTaskDelegate != null)
217                 {
218                     return createTaskDelegate;
219                 }
220
221                 lock (createGenericTaskDelegateCache)
222                 {
223                     createTaskDelegate = createGenericTaskDelegateCache[taskResultType] as Func<ServiceChannel, ProxyOperationRuntime, object[], Task>;
224                     if (createTaskDelegate != null)
225                     {
226                         return createTaskDelegate;
227                     }
228                     
229                     MethodInfo methodInfo = createGenericTaskMI.MakeGenericMethod(taskResultType);
230                     createTaskDelegate = Delegate.CreateDelegate(typeof(Func<ServiceChannel, ProxyOperationRuntime, object[], Task>), methodInfo) as Func<ServiceChannel, ProxyOperationRuntime, object[], Task>;
231                     createGenericTaskDelegateCache[taskResultType] = createTaskDelegate;
232                 }
233
234                 return createTaskDelegate;
235             }
236
237             public static Task CreateTask(ServiceChannel channel, IMethodCallMessage methodCall, ProxyOperationRuntime operation)
238             {
239                 if (operation.TaskTResult == ServiceReflector.VoidType)
240                 {
241                     return TaskCreator.CreateTask(channel, operation, methodCall.InArgs);
242                 }
243                 return TaskCreator.CreateGenericTask(channel, operation, methodCall.InArgs);
244             }
245
246             static Task CreateGenericTask(ServiceChannel channel, ProxyOperationRuntime operation, object[] inputParameters)
247             {
248                 Func<ServiceChannel, ProxyOperationRuntime, object[], Task> createTaskDelegate = GetOrCreateTaskDelegate(operation.TaskTResult);
249                 return createTaskDelegate(channel, operation, inputParameters);
250             }
251
252             static Task CreateTask(ServiceChannel channel, ProxyOperationRuntime operation, object[] inputParameters)
253             {
254                 Action<IAsyncResult> endCallDelegate = (asyncResult) =>
255                 {
256                     Fx.Assert(asyncResult != null, "'asyncResult' MUST NOT be NULL.");
257                     OperationContext originalOperationContext = OperationContext.Current;
258                     OperationContext.Current = asyncResult.AsyncState as OperationContext;
259                     try
260                     {
261                         channel.EndCall(operation.Action, ProxyOperationRuntime.EmptyArray, asyncResult);
262                     }
263                     finally
264                     {
265                         OperationContext.Current = originalOperationContext;
266                     }
267                 };
268
269                 return Task.Factory.FromAsync(beginCallDelegate, endCallDelegate, channel, operation, inputParameters, OperationContext.Current);
270             }
271
272             public static Task<T> CreateGenericTask<T>(ServiceChannel channel, ProxyOperationRuntime operation, object[] inputParameters)
273             {
274                 Func<IAsyncResult, T> endCallDelegate = (asyncResult) =>
275                 {
276                     OperationContext originalOperationContext = OperationContext.Current;
277                     OperationContext.Current = asyncResult.AsyncState as OperationContext;
278                     try
279                     {
280                         return (T)channel.EndCall(operation.Action, ProxyOperationRuntime.EmptyArray, asyncResult);
281                     }
282                     finally
283                     {
284                         OperationContext.Current = originalOperationContext;
285                     }
286                 };
287
288                 return Task<T>.Factory.FromAsync<ServiceChannel, ProxyOperationRuntime, object[]>(beginCallDelegate, endCallDelegate, channel, operation, inputParameters, OperationContext.Current);
289             }
290         }
291
292         IMessage InvokeTaskService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
293         {
294             Task task = TaskCreator.CreateTask(this.serviceChannel, methodCall, operation);
295             return CreateReturnMessage(task, null, methodCall);
296         }
297
298         IMethodReturnMessage InvokeChannel(IMethodCallMessage methodCall)
299         {
300             string activityName = null;
301             ActivityType activityType = ActivityType.Unknown;
302             if (DiagnosticUtility.ShouldUseActivity)
303             {
304                 if (ServiceModelActivity.Current == null ||
305                     ServiceModelActivity.Current.ActivityType != ActivityType.Close)
306                 {
307                     MethodData methodData = this.GetMethodData(methodCall);
308                     if (methodData.MethodBase.DeclaringType == typeof(System.ServiceModel.ICommunicationObject)
309                         && methodData.MethodBase.Name.Equals("Close", StringComparison.Ordinal))
310                     {
311                         activityName = SR.GetString(SR.ActivityClose, this.serviceChannel.GetType().FullName);
312                         activityType = ActivityType.Close;
313                     }
314                 }
315             }
316
317             using (ServiceModelActivity activity = string.IsNullOrEmpty(activityName) ? null : ServiceModelActivity.CreateBoundedActivity())
318             {
319                 if (DiagnosticUtility.ShouldUseActivity)
320                 {
321                     ServiceModelActivity.Start(activity, activityName, activityType);
322                 }
323                 return ExecuteMessage(this.serviceChannel, methodCall);
324             }
325         }
326
327         IMethodReturnMessage InvokeGetType(IMethodCallMessage methodCall)
328         {
329             return CreateReturnMessage(proxiedType, null, 0, SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext), methodCall);
330         }
331
332         IMethodReturnMessage InvokeObject(IMethodCallMessage methodCall)
333         {
334             return RemotingServices.ExecuteMessage(this.objectWrapper, methodCall);
335         }
336
337         IMethodReturnMessage InvokeBeginService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
338         {
339             AsyncCallback callback;
340             object asyncState;
341             object[] ins = operation.MapAsyncBeginInputs(methodCall, out callback, out asyncState);
342             object ret = this.serviceChannel.BeginCall(operation.Action, operation.IsOneWay, operation, ins, callback, asyncState);
343             return CreateReturnMessage(ret, null, methodCall);
344         }
345
346         IMethodReturnMessage InvokeEndService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
347         {
348             IAsyncResult result;
349             object[] outs;
350             operation.MapAsyncEndInputs(methodCall, out result, out outs);
351             object ret = this.serviceChannel.EndCall(operation.Action, outs, result);
352             object[] returnArgs = operation.MapAsyncOutputs(methodCall, outs, ref ret);
353             return CreateReturnMessage(ret, returnArgs, methodCall);
354         }
355
356         IMethodReturnMessage InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
357         {
358             object[] outs;
359             object[] ins = operation.MapSyncInputs(methodCall, out outs);
360             object ret = this.serviceChannel.Call(operation.Action, operation.IsOneWay, operation, ins, outs);
361             object[] returnArgs = operation.MapSyncOutputs(methodCall, outs, ref ret);
362             return CreateReturnMessage(ret, returnArgs, methodCall);
363         }
364
365         IMethodReturnMessage ExecuteMessage(object target, IMethodCallMessage methodCall)
366         {
367             MethodBase targetMethod = methodCall.MethodBase;
368
369             object[] args = methodCall.Args;
370             object returnValue = null;
371             try
372             {
373                 returnValue = targetMethod.Invoke(target, args);
374             }
375             catch (TargetInvocationException e)
376             {
377                 return CreateReturnMessage(e.InnerException, methodCall);
378             }
379
380             return CreateReturnMessage(returnValue,
381                                        args,
382                                        args.Length,
383                                        null,
384                                        methodCall);
385         }
386
387         bool IRemotingTypeInfo.CanCastTo(Type toType, object o)
388         {
389             return toType.IsAssignableFrom(proxiedType) || serviceChannel.CanCastTo(toType);
390         }
391
392         string IRemotingTypeInfo.TypeName
393         {
394             get { return proxiedType.FullName; }
395             set { }
396         }
397
398         class MethodDataCache
399         {
400             MethodData[] methodDatas;
401
402             public MethodDataCache()
403             {
404                 this.methodDatas = new MethodData[4];
405             }
406
407             object ThisLock
408             {
409                 get { return this; }
410             }
411
412             public bool TryGetMethodData(MethodBase method, out MethodData methodData)
413             {
414                 lock (ThisLock)
415                 {
416                     MethodData[] methodDatas = this.methodDatas;
417                     int index = FindMethod(methodDatas, method);
418                     if (index >= 0)
419                     {
420                         methodData = methodDatas[index];
421                         return true;
422                     }
423                     else
424                     {
425                         methodData = new MethodData();
426                         return false;
427                     }
428                 }
429             }
430
431             static int FindMethod(MethodData[] methodDatas, MethodBase methodToFind)
432             {
433                 for (int i = 0; i < methodDatas.Length; i++)
434                 {
435                     MethodBase method = methodDatas[i].MethodBase;
436                     if (method == null)
437                     {
438                         break;
439                     }
440                     if (method == methodToFind)
441                     {
442                         return i;
443                     }
444                 }
445                 return -1;
446             }
447
448             public void SetMethodData(MethodData methodData)
449             {
450                 lock (ThisLock)
451                 {
452                     int index = FindMethod(this.methodDatas, methodData.MethodBase);
453                     if (index < 0)
454                     {
455                         for (int i = 0; i < this.methodDatas.Length; i++)
456                         {
457                             if (methodDatas[i].MethodBase == null)
458                             {
459                                 methodDatas[i] = methodData;
460                                 return;
461                             }
462                         }
463                         MethodData[] newMethodDatas = new MethodData[methodDatas.Length * 2];
464                         Array.Copy(methodDatas, newMethodDatas, methodDatas.Length);
465                         newMethodDatas[methodDatas.Length] = methodData;
466                         this.methodDatas = newMethodDatas;
467                     }
468                 }
469             }
470         }
471
472         enum MethodType
473         {
474             Service,
475             BeginService,
476             EndService,
477             Channel,
478             Object,
479             GetType,
480             TaskService
481         }
482
483         struct MethodData
484         {
485             MethodBase methodBase;
486             MethodType methodType;
487             ProxyOperationRuntime operation;
488
489             public MethodData(MethodBase methodBase, MethodType methodType)
490                 : this(methodBase, methodType, null)
491             {
492             }
493
494             public MethodData(MethodBase methodBase, MethodType methodType, ProxyOperationRuntime operation)
495             {
496                 this.methodBase = methodBase;
497                 this.methodType = methodType;
498                 this.operation = operation;
499             }
500
501             public MethodBase MethodBase
502             {
503                 get { return methodBase; }
504             }
505
506             public MethodType MethodType
507             {
508                 get { return methodType; }
509             }
510
511             public ProxyOperationRuntime Operation
512             {
513                 get { return operation; }
514             }
515         }
516
517         class MbrObject : MarshalByRefObject
518         {
519             RealProxy proxy;
520             Type targetType;
521
522             internal MbrObject(RealProxy proxy, Type targetType)
523             {
524                 this.proxy = proxy;
525                 this.targetType = targetType;
526             }
527
528             public override bool Equals(object obj)
529             {
530                 return Object.ReferenceEquals(obj, this.proxy.GetTransparentProxy());
531             }
532
533             public override string ToString()
534             {
535                 return this.targetType.ToString();
536             }
537
538             public override int GetHashCode()
539             {
540                 return this.proxy.GetHashCode();
541             }
542         }
543
544         class SingleReturnMessage : IMethodReturnMessage
545         {
546             IMethodCallMessage methodCall;
547             object ret;
548             PropertyDictionary properties;
549
550             public SingleReturnMessage(object ret, IMethodCallMessage methodCall)
551             {
552                 this.ret = ret;
553                 this.methodCall = methodCall;
554                 this.properties = new PropertyDictionary();
555             }
556
557             public int ArgCount
558             {
559                 get { return 0; }
560             }
561
562             public object[] Args
563             {
564                 get { return EmptyArray.Instance; }
565             }
566
567             public Exception Exception
568             {
569                 get { return null; }
570             }
571
572             public bool HasVarArgs
573             {
574                 get { return methodCall.HasVarArgs; }
575             }
576
577             public LogicalCallContext LogicalCallContext
578             {
579                 get { return SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext); }
580             }
581
582             public MethodBase MethodBase
583             {
584                 get { return methodCall.MethodBase; }
585             }
586
587             public string MethodName
588             {
589                 get { return methodCall.MethodName; }
590             }
591
592             public object MethodSignature
593             {
594                 get { return methodCall.MethodSignature; }
595             }
596
597             public object[] OutArgs
598             {
599                 get { return EmptyArray.Instance; }
600             }
601
602             public int OutArgCount
603             {
604                 get { return 0; }
605             }
606
607             public IDictionary Properties
608             {
609                 get { return properties; }
610             }
611
612             public object ReturnValue
613             {
614                 get { return ret; }
615             }
616
617             public string TypeName
618             {
619                 get { return methodCall.TypeName; }
620             }
621
622             public string Uri
623             {
624                 get { return null; }
625             }
626
627             public object GetArg(int index)
628             {
629                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
630             }
631
632             public string GetArgName(int index)
633             {
634                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
635             }
636
637             public object GetOutArg(int index)
638             {
639                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
640             }
641
642             public string GetOutArgName(int index)
643             {
644                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
645             }
646
647             class PropertyDictionary : IDictionary
648             {
649                 ListDictionary properties;
650
651                 public object this[object key]
652                 {
653                     get { return Properties[key]; }
654                     set { Properties[key] = value; }
655                 }
656
657                 public int Count
658                 {
659                     get { return Properties.Count; }
660                 }
661
662                 public bool IsFixedSize
663                 {
664                     get { return false; }
665                 }
666
667                 public bool IsReadOnly
668                 {
669                     get { return false; }
670                 }
671
672                 public bool IsSynchronized
673                 {
674                     get { return false; }
675                 }
676
677                 public ICollection Keys
678                 {
679                     get { return Properties.Keys; }
680                 }
681
682                 ListDictionary Properties
683                 {
684                     get
685                     {
686                         if (properties == null)
687                         {
688                             properties = new ListDictionary();
689                         }
690                         return properties;
691                     }
692                 }
693
694                 public ICollection Values
695                 {
696                     get { return Properties.Values; }
697                 }
698
699                 public object SyncRoot
700                 {
701                     get { return null; }
702                 }
703
704                 public void Add(object key, object value)
705                 {
706                     Properties.Add(key, value);
707                 }
708
709                 public void Clear()
710                 {
711                     Properties.Clear();
712                 }
713
714                 public bool Contains(object key)
715                 {
716                     return Properties.Contains(key);
717                 }
718
719                 public void CopyTo(Array array, int index)
720                 {
721                     Properties.CopyTo(array, index);
722                 }
723
724                 public IDictionaryEnumerator GetEnumerator()
725                 {
726                     if (properties == null)
727                     {
728                         return EmptyEnumerator.Instance;
729                     }
730                     else
731                     {
732                         return properties.GetEnumerator();
733                     }
734                 }
735
736                 IEnumerator IEnumerable.GetEnumerator()
737                 {
738                     return ((IEnumerable)Properties).GetEnumerator();
739                 }
740
741                 public void Remove(object key)
742                 {
743                     Properties.Remove(key);
744                 }
745
746                 class EmptyEnumerator : IDictionaryEnumerator
747                 {
748                     static EmptyEnumerator instance = new EmptyEnumerator();
749
750                     EmptyEnumerator()
751                     {
752                     }
753
754                     public static EmptyEnumerator Instance
755                     {
756                         get { return instance; }
757                     }
758
759                     public bool MoveNext()
760                     {
761                         return false;
762                     }
763
764                     public Object Current
765                     {
766                         get
767                         {
768 #pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
769                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty)));
770                         }
771                     }
772
773                     public void Reset()
774                     {
775                     }
776
777                     public Object Key
778                     {
779                         get
780                         {
781 #pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
782                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty)));
783                         }
784                     }
785
786                     public Object Value
787                     {
788                         get
789                         {
790 #pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
791                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty)));
792                         }
793                     }
794
795                     public DictionaryEntry Entry
796                     {
797                         get
798                         {
799 #pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
800                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty)));
801                         }
802                     }
803                 }
804             }
805         }
806     }
807 }