Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / remoting / remotingproxy.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** File:    RemotingProxy.cs
9 **
10 **
11 ** Purpose: Defines the general purpose remoting proxy
12 **
13 **
14 ===========================================================*/
15 namespace System.Runtime.Remoting.Proxies {
16     using System.Threading;
17     using System.Runtime.Remoting.Activation;
18     using System.Runtime.Remoting.Messaging;    
19     using System.Runtime.Remoting.Contexts;
20     using System.Runtime.Remoting.Channels;
21     using System;
22     using MethodInfo = System.Reflection.MethodInfo;
23     using MethodBase = System.Reflection.MethodBase;
24     using System.Globalization;
25     // Remoting proxy
26     [System.Security.SecurityCritical]  // auto-generated
27     internal class RemotingProxy : RealProxy, IRemotingTypeInfo 
28     {
29         // Static Fields
30         private static MethodInfo _getTypeMethod = typeof(System.Object).GetMethod("GetType");
31         private static MethodInfo _getHashCodeMethod = typeof(System.Object).GetMethod("GetHashCode");
32
33         private static RuntimeType s_typeofObject = (RuntimeType)typeof(System.Object);
34         private static RuntimeType s_typeofMarshalByRefObject = (RuntimeType)typeof(System.MarshalByRefObject);
35
36         //*******************WARNING******************************************
37         // If you change the names of these fields then change the corresponding
38         // names in remoting.cpp 
39         //********************************************************************        
40         private ConstructorCallMessage _ccm;
41         private int _ctorThread;
42             
43
44         // Constructor
45         public RemotingProxy(Type serverType)        
46         : base(serverType) 
47         {            
48         }
49
50         private RemotingProxy()
51         {
52             // Prevent anyone from creating a blank instance of a proxy
53             // without the underlying server type
54         }
55
56         internal int CtorThread
57         {
58             get
59             {
60                 return _ctorThread;
61             }
62             set
63             {
64                 //NOTE : the assert below is correct for activated objects. 
65                 //But for a connected object (where new XXX() does a Connect()
66                 //the InternalActivate codepath may execute twice .. since
67                 //we would be returning the same proxy for multiple calls to
68                 //new XXX() & JIT would try to execute the default .ctor on
69                 //the returned proxy. 
70                 
71                 //BCLDebug.Assert(_ctorThread == 0, "ctorThread already set??");
72                 _ctorThread = value;
73             }
74         }
75
76         // This is used when a TP is called with SyncProcessMessage
77         internal static IMessage CallProcessMessage(IMessageSink ms, 
78                                                     IMessage reqMsg, 
79                                                     ArrayWithSize proxySinks,
80                                                     Thread currentThread,
81                                                     Context currentContext,
82                                                     bool bSkippingContextChain)
83         {                   
84             // Notify Dynamic Sinks: CALL starting          
85             if (proxySinks != null)
86             {
87                 DynamicPropertyHolder.NotifyDynamicSinks(
88                                             reqMsg, 
89                                             proxySinks, 
90                                             true,   // bCliSide
91                                             true,   // bStart
92                                             false); // bAsync
93             }
94
95             bool bHasDynamicSinks = false;
96             if (bSkippingContextChain)
97             {
98                 // this would have been done in the client context terminator sink
99                 bHasDynamicSinks = 
100                     currentContext.NotifyDynamicSinks(reqMsg, 
101                         true,   // bCliSide
102                         true,   // bStart
103                         false,  // bAsync
104                         true);  // bNotifyGlobals 
105    
106                 ChannelServices.NotifyProfiler(reqMsg, RemotingProfilerEvent.ClientSend);
107             }
108             
109             if (ms == null)
110             {
111                 throw new RemotingException(
112                     Environment.GetResourceString(
113                         "Remoting_Proxy_NoChannelSink"));                    
114             }
115
116             IMessage retMsg = ms.SyncProcessMessage(reqMsg);
117
118             if (bSkippingContextChain)
119             {
120                 // this would have been done in the client context terminator sink
121                 ChannelServices.NotifyProfiler(retMsg, RemotingProfilerEvent.ClientReceive);
122
123                 if (bHasDynamicSinks)
124                 {
125                     currentContext.NotifyDynamicSinks(
126                         retMsg, 
127                         true,   // bCliSide
128                         false,   // bStart
129                         false,  // bAsync
130                         true);  // bNotifyGlobals  
131                 }
132             }            
133
134             IMethodReturnMessage mrm = retMsg as IMethodReturnMessage;
135             if (retMsg == null || mrm == null)
136             {
137                 throw new RemotingException(
138                     Environment.GetResourceString("Remoting_Message_BadType"));                    
139             }
140
141             // notify DynamicSinks: CALL returned
142             if (proxySinks != null)
143             {
144                 DynamicPropertyHolder.NotifyDynamicSinks(
145                                             retMsg, 
146                                             proxySinks, 
147                                             true,   // bCliSide
148                                             false,  // bStart
149                                             false); // bAsync
150             }
151
152            
153             return retMsg;
154         }
155
156         // Implement Invoke
157         [System.Security.SecurityCritical]
158         public override IMessage Invoke(IMessage reqMsg) 
159         {
160             // Dispatch based on whether its a constructor call
161             // or a method call
162
163             IConstructionCallMessage ccm = reqMsg as IConstructionCallMessage;        
164             
165             if(ccm != null)
166             {
167                 // Activate
168                 return InternalActivate(ccm);
169             }
170             else
171             {
172                 // Handle regular method calls
173
174                 // Check that the initialization has completed
175                 if(!Initialized)
176                 {
177                     // This covers the case where an object may call out
178                     // on another object passing its "this" pointer during its
179                     // .ctor. 
180                     // The other object attempting to call on the this pointer
181                     // (in x-context case) would be calling on a proxy not
182                     // marked fully initialized. 
183                     // <
184
185
186
187                     // Let the original constructor thread go through but 
188                     // throw for other threads. 
189                     if (CtorThread == Thread.CurrentThread.GetHashCode())
190                     {
191                         ServerIdentity srvId = IdentityObject as ServerIdentity;
192                         BCLDebug.Assert(
193                             srvId != null
194                             && 
195                             ((ServerIdentity)IdentityObject).ServerContext != null,
196                             "Wrap may associate with wrong context!");
197
198                         // If we are here, the server object passed itself 
199                         // out to another x-context object during the .ctor
200                         // That guy is calling us back. Let us call Wrap() 
201                         // earlier than usual so that envoy & channel sinks
202                         // get set up!
203                         // <
204
205
206
207                         RemotingServices.Wrap( 
208                             (ContextBoundObject) this.UnwrappedServerObject);
209
210                     }
211                     else
212                     {
213                         // Throw an exception to indicate that we are 
214                         // calling on a proxy while the constructor call 
215                         // is still running.
216                         throw new RemotingException(Environment.GetResourceString("Remoting_Proxy_InvalidCall"));
217                     }
218                     
219                 }
220                 
221                 // Dispatch
222                 int callType = Message.Sync;
223                 Message msg = reqMsg as Message;
224                 if (msg != null)
225                 {
226                     callType = msg.GetCallType(); 
227                 }                
228                 
229                 return InternalInvoke((IMethodCallMessage)reqMsg, false, callType);
230             }
231             
232         } // Invoke
233         
234
235         // This is called for all remoted calls on a TP except Ctors
236         // The method called may be [....], Async or OneWay(special case of Async)
237         // In the Async case we come here for both BeginInvoke & EndInvoke
238         internal virtual IMessage InternalInvoke(
239             IMethodCallMessage reqMcmMsg, bool useDispatchMessage, int callType)
240         {
241             Message reqMsg = reqMcmMsg as Message;            
242             if ((reqMsg == null) && (callType != Message.Sync))
243             {
244                 // Only the synchronous call type is supported for messages that
245                 //   aren't of type Message.               
246                 throw new RemotingException(
247                     Environment.GetResourceString("Remoting_Proxy_InvalidCallType"));
248             }
249         
250             IMessage retMsg = null;
251             Thread currentThread = Thread.CurrentThread;
252
253             // pick up call context from the thread
254             LogicalCallContext cctx = currentThread.GetMutableExecutionContext().LogicalCallContext;
255
256             Identity idObj = IdentityObject;
257             ServerIdentity serverID = idObj as ServerIdentity;
258             if ((null != serverID) && idObj.IsFullyDisconnected())
259             {
260                 throw new ArgumentException(
261                    Environment.GetResourceString("Remoting_ServerObjectNotFound", reqMcmMsg.Uri));
262             }
263
264             // Short-circuit calls to Object::GetType and Object::GetHashCode
265             MethodBase mb = reqMcmMsg.MethodBase;
266             if(_getTypeMethod == mb)
267             {
268                 // Time to load the true type of the remote object....
269                 Type t = GetProxiedType();
270                 return new ReturnMessage(t, null, 0, cctx, reqMcmMsg);
271             }
272
273             if (_getHashCodeMethod == mb)
274             {
275                 int hashCode = idObj.GetHashCode();
276                 return new ReturnMessage(hashCode, null, 0, cctx, reqMcmMsg);
277             }
278
279             // check for channel sink
280             if (idObj.ChannelSink == null)
281             {
282                 IMessageSink chnlSink = null;
283                 IMessageSink envoySink = null;
284                 // If channelSink is null try to Create them again
285                 // the objref should be correctly fixed up at this point
286                 if(!idObj.ObjectRef.IsObjRefLite())
287                 {
288                     RemotingServices.CreateEnvoyAndChannelSinks(null, idObj.ObjectRef, out chnlSink, out envoySink);
289                 }
290                 else
291                 {
292                     RemotingServices.CreateEnvoyAndChannelSinks(idObj.ObjURI, null, out chnlSink, out envoySink);
293                 }
294                 // Set the envoy and channel sinks in a thread safe manner
295                 RemotingServices.SetEnvoyAndChannelSinks(idObj, chnlSink, envoySink);
296
297                 // If the channel sink is still null then throw
298                 if(idObj.ChannelSink == null)
299                 {
300                     throw new RemotingException(
301                         Environment.GetResourceString("Remoting_Proxy_NoChannelSink"));
302                 }
303             }
304
305             // Set the identity in the message object
306             IInternalMessage iim = (IInternalMessage)reqMcmMsg;
307             iim.IdentityObject = idObj;
308
309             if (null != serverID)
310             {
311                 Message.DebugOut("Setting serveridentity on message \n");
312                 iim.ServerIdentityObject = serverID;
313                     
314             }
315             else
316             {
317                 // We need to set the URI only for identities that 
318                 // are not the server identities. The uri is used to
319                 // dispatch methods for objects outside the appdomain.
320                 // Inside the appdomain (xcontext case) we dispatch 
321                 // by getting the server object from the server identity.
322                iim.SetURI(idObj.URI);
323             }       
324
325             Message.DebugOut("InternalInvoke. Dispatching based on class type\n");
326             AsyncResult ar = null;
327             switch (callType)
328             {
329             case Message.Sync:
330                 Message.DebugOut("RemotingProxy.Invoke Call: SyncProcessMsg\n");
331                 BCLDebug.Assert(!useDispatchMessage,"!useDispatchMessage");                
332                 bool bSkipContextChain = false;
333                 Context currentContext = currentThread.GetCurrentContextInternal();
334                 IMessageSink nextSink = idObj.EnvoyChain;
335
336                 // if we are in the default context, there can be no 
337                 // client context chain, so we can skip the intermediate 
338                 // calls if there are no envoy sinks
339
340                 if (currentContext.IsDefaultContext)
341                 {
342                     if (nextSink is EnvoyTerminatorSink)
343                     {
344                         bSkipContextChain = true;
345
346                         // jump directly to the channel sink
347                         nextSink = idObj.ChannelSink;
348                     }
349                 }
350
351                 retMsg = CallProcessMessage(nextSink,
352                                             reqMcmMsg, 
353                                             idObj.ProxySideDynamicSinks,
354                                             currentThread,
355                                             currentContext,
356                                             bSkipContextChain);
357
358                 break;
359
360             case Message.BeginAsync:
361             case Message.BeginAsync | Message.OneWay:                                        
362                 // For async calls we clone the call context from the thread
363                 // This is a limited clone (we dont deep copy the user data)
364                 cctx = (LogicalCallContext) cctx.Clone(); 
365                 iim.SetCallContext(cctx);  
366                 
367                 ar = new AsyncResult(reqMsg);
368               
369                 InternalInvokeAsync(ar, reqMsg, useDispatchMessage, callType);
370
371                 Message.DebugOut("Propagate out params for BeginAsync\n");
372                 retMsg = new ReturnMessage(ar, null, 0, null/*cctx*/, reqMsg);
373                 break;
374
375             case Message.OneWay:
376                 // For async calls we clone the call context from the thread
377                 // This is a limited clone (we dont deep copy the user data)
378                 cctx = (LogicalCallContext) cctx.Clone();
379                 iim.SetCallContext(cctx);
380                 InternalInvokeAsync(null, reqMsg, useDispatchMessage, callType);
381                 retMsg = new ReturnMessage(null, null, 0, null/*cctx*/, reqMcmMsg);
382                 break;
383
384             case (Message.EndAsync | Message.OneWay):
385                 retMsg = new ReturnMessage(null, null, 0, null/*cctx*/, reqMcmMsg);
386                 break;
387
388             case Message.EndAsync:
389                 // For endAsync, we merge back the returned callContext
390                 // into the thread's callContext
391                 retMsg = RealProxy.EndInvokeHelper(reqMsg, true);
392                 break;
393             }
394             
395             return retMsg;
396         }
397
398
399         // This is called from InternalInvoke above when someone makes an
400         // Async (or a one way) call on a TP
401         internal void InternalInvokeAsync(IMessageSink ar,  Message reqMsg, 
402             bool useDispatchMessage, int callType)
403         {
404             IMessageCtrl cc = null;
405             Identity idObj = IdentityObject;
406             ServerIdentity serverID = idObj as ServerIdentity;
407             MethodCall cpyMsg= new MethodCall(reqMsg);
408             IInternalMessage iim = ((IInternalMessage)cpyMsg);
409
410             // Set the identity in the message object
411             iim.IdentityObject = idObj;
412             if (null != serverID)
413             {
414                 Message.DebugOut("Setting SrvID on deser msg\n");
415                 iim.ServerIdentityObject = serverID;                    
416             }
417
418             if (useDispatchMessage)
419             {
420                 Message.DebugOut(
421                     "RemotingProxy.Invoke: Calling AsyncDispatchMessage\n");
422
423                 BCLDebug.Assert(ar != null,"ar != null");
424                 BCLDebug.Assert( (callType & Message.BeginAsync) != 0,
425                                 "BeginAsync flag not set!");
426
427                 Message.DebugOut("Calling AsynDispatchMessage \n");
428                 cc = ChannelServices.AsyncDispatchMessage(
429                                         cpyMsg, 
430                                         ((callType & Message.OneWay) != 0) 
431                                         ? null : ar);
432             }
433             else if (null != idObj.EnvoyChain)
434             {
435                 Message.DebugOut("RemotingProxy.Invoke: Calling AsyncProcessMsg on the envoy chain\n");
436
437                 cc = idObj.EnvoyChain.AsyncProcessMessage(
438                                         cpyMsg, 
439                                         ((callType & Message.OneWay) != 0) 
440                                         ? null : ar);
441             }
442             else
443             {
444                 // Channel sink cannot be null since it is the last sink in
445                 // the client context
446                 // Assert if Invoke is called without a channel sink
447                 BCLDebug.Assert(false, "How did we get here?");
448                 
449                 throw new InvalidOperationException(
450                     Environment.GetResourceString("Remoting_Proxy_InvalidState"));
451             }
452
453             if ((callType & Message.BeginAsync) != 0)
454             {
455
456                 if ((callType & Message.OneWay) != 0)
457                 {
458                     ar.SyncProcessMessage(null);
459                 }
460             }
461         }
462
463         // New method for activators.
464         
465         // This gets called during remoting intercepted activation when 
466         // JIT tries to run a constructor on a TP (which remoting gave it
467         // in place of an actual uninitialized instance of the expected type)
468         private IConstructionReturnMessage InternalActivate(IConstructionCallMessage ctorMsg)
469         {
470             // Remember the hashcode of the constructor thread.
471             CtorThread = Thread.CurrentThread.GetHashCode();
472
473             IConstructionReturnMessage ctorRetMsg = ActivationServices.Activate(this, ctorMsg);
474
475             // Set the flag to indicate that the object is initialized
476             // Note: this assert is not valid for WKOs
477             //BCLDebug.Assert(!Initialized, "Proxy marked as initialized before activation call completed");
478             Initialized = true;
479
480             return ctorRetMsg;
481         }
482
483         // Invoke for case where call is in the same context as the server object
484         // (This special static method is used for AsyncDelegate-s ... this is called
485         // directly from the EE)
486         private static void Invoke(Object NotUsed, ref MessageData msgData)
487         {
488             Message m = new Message();
489             m.InitFields(msgData);
490
491             Object thisPtr = m.GetThisPtr();
492             Delegate d;
493             if ((d = thisPtr as Delegate) != null)
494             {
495                 // <
496
497                 RemotingProxy rp = (RemotingProxy)
498                     RemotingServices.GetRealProxy(d.Target);
499
500                 if (rp != null)
501                 {
502                     rp.InternalInvoke(m, true, m.GetCallType());
503                 }
504                 else
505                 {
506                     int callType = m.GetCallType();       
507                     AsyncResult ar;
508                     switch (callType)
509                     {
510                     case Message.BeginAsync:
511                     case Message.BeginAsync | Message.OneWay:
512                         // pick up call context from the thread
513                         m.Properties[Message.CallContextKey] =
514                             Thread.CurrentThread.GetMutableExecutionContext().LogicalCallContext.Clone();
515                         ar = new AsyncResult(m);
516                         AgileAsyncWorkerItem  workItem = 
517                             new AgileAsyncWorkerItem(
518                                     m, 
519                                     ((callType & Message.OneWay) != 0) ? 
520                                         null : ar, d.Target);
521
522                         ThreadPool.QueueUserWorkItem(
523                             new WaitCallback(
524                                     AgileAsyncWorkerItem.ThreadPoolCallBack),
525                             workItem);
526
527                         if ((callType & Message.OneWay) != 0)
528                         {
529                             ar.SyncProcessMessage(null);
530                         }
531                         m.PropagateOutParameters(null, ar);
532                         break;
533                     case (Message.EndAsync | Message.OneWay):
534                         return;
535
536                     case Message.EndAsync:
537                         // This will also merge back the call context
538                         // onto the thread that called EndAsync
539                         RealProxy.EndInvokeHelper(m, false);
540                         break;
541                     default:
542                         BCLDebug.Assert(
543                             false, 
544                             "Should never be here. Sync delegate code for agile object ended up in remoting");
545                         break;
546                     }
547                 }
548             }
549             else
550             {
551                 // Static invoke called with incorrect this pointer ...
552                 throw new RemotingException(
553                     Environment.GetResourceString(
554                         "Remoting_Default"));                    
555             }
556         }
557
558         internal ConstructorCallMessage ConstructorMessage
559         {
560             get
561             {
562                 return _ccm;
563             }
564
565             set
566             {
567                 _ccm = value;
568             }
569         }
570
571         //
572         // IRemotingTypeInfo interface
573         //
574
575         // Obtain the fully qualified name of the type that the proxy represents
576         public String TypeName 
577         {
578             [System.Security.SecurityCritical]
579             get
580             {
581                 return GetProxiedType().FullName;
582             }
583
584             [System.Security.SecurityCritical]
585             set
586             {
587                 throw new NotSupportedException();
588             }
589         }
590
591         // interop methods
592         [System.Security.SecurityCritical]
593         public override IntPtr GetCOMIUnknown(bool fIsBeingMarshalled)
594         {
595             IntPtr pUnk = IntPtr.Zero;
596             Object otp = GetTransparentProxy();            
597             bool fIsXProcess = RemotingServices.IsObjectOutOfProcess(otp);
598             if (fIsXProcess)
599             {
600                 // we are in a different process
601                 if (fIsBeingMarshalled)
602                 {
603                     // we need to go to the server to get the real IUnknown
604                     pUnk =  MarshalByRefObject.GetComIUnknown((MarshalByRefObject)otp);
605                 }
606                 else
607                 {
608                     // create an IUnknown here
609                     pUnk =  MarshalByRefObject.GetComIUnknown((MarshalByRefObject)otp);    
610                 }
611             }
612             else
613             {
614                 bool fIsXAppDomain = RemotingServices.IsObjectOutOfAppDomain(otp);
615                 // we are in the same proces, ask the object for its IUnknown
616                 if (fIsXAppDomain)
617                 {
618                     // do an appdomain switch
619                     pUnk = ((MarshalByRefObject)otp).GetComIUnknown(fIsBeingMarshalled);
620                 }
621                 else
622                 {    
623                     // otherwise go ahead and create a CCW here
624                     pUnk = MarshalByRefObject.GetComIUnknown((MarshalByRefObject)otp);
625                 }
626             }
627
628             return pUnk;
629         }
630
631         [System.Security.SecurityCritical]
632         public override void SetCOMIUnknown(IntPtr i)
633         {
634             // for now ignore this
635         }
636
637         // Check whether we can cast the transparent proxy to the given type
638         [System.Security.SecurityCritical]
639         public bool CanCastTo(Type castType, Object o)
640         {
641             if (castType == null)
642                 throw new ArgumentNullException("castType");
643
644             RuntimeType rtType = castType as RuntimeType;
645             if (rtType == null)
646                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
647
648             bool fCastOK = false;
649
650             // The identity should be non-null
651             BCLDebug.Assert(null != IdentityObject,"null != IdentityObject");
652
653             Message.DebugOut("CheckCast for identity " + IdentityObject.GetType());
654
655             if ((rtType == s_typeofObject) ||
656                 (rtType == s_typeofMarshalByRefObject))
657             {
658                 return true;
659             }
660
661             // Get the objref of the proxy
662             ObjRef oRef = IdentityObject.ObjectRef;
663
664             // If the object ref is non-null then check against the type info
665             // stored in the it
666             if (null != oRef)
667             {
668                 Object oTP = GetTransparentProxy();
669
670                 // Check that there is a matching type in the server object 
671                 // hierarchy represented in the objref                                      
672                 Message.DebugOut("Calling CanCastTo for type " + rtType);
673                 IRemotingTypeInfo typeInfo = oRef.TypeInfo;
674                 if(null != typeInfo)
675                 {
676                     fCastOK = typeInfo.CanCastTo(rtType, oTP);
677                     if (!fCastOK && typeInfo.GetType()==typeof(TypeInfo) && oRef.IsWellKnown() )
678                     {
679                         fCastOK = CanCastToWK(rtType);
680                     }
681                 }                                
682                 else
683                 {
684                     if (oRef.IsObjRefLite())
685                     {
686                         // we should do a dynamic cast across the network
687                         fCastOK = MarshalByRefObject.CanCastToXmlTypeHelper(rtType, (MarshalByRefObject)o);  
688                     }
689                 }
690             }
691             // This is a well known object which does not have a backing ObjRef
692             else
693             {
694                 fCastOK = CanCastToWK(rtType);
695             }
696             return fCastOK;
697         }
698
699         // WellKnown proxies we always allow casts to interfaces, and allow 
700         // casting down a single branch in the type hierarchy (both are on good
701         // faith. The calls are failed on server side if a bogus cast is done)
702         bool CanCastToWK(Type castType)
703         {
704             Message.DebugOut( "CheckCast for well known objects and type " + castType);
705             bool fCastOK = false;
706             // Check whether the type to which we want to cast is
707             // compatible with the current type
708             if(castType.IsClass)
709             {
710                 fCastOK = GetProxiedType().IsAssignableFrom(castType);
711             }
712             else
713             {
714                 // NOTE: we are coming here also for x-context proxies
715                 // when unmanaged code cannot determine if the cast is not
716                 // okay <
717                 if (!(IdentityObject is ServerIdentity))
718                 {
719                     BCLDebug.Assert(
720                         IdentityObject.URI != null,
721                         "Bad WellKnown ID");
722                     // Always allow interface casts to succeed. If the 
723                     // interface is not supported by the well known object
724                     // then we will throw an exception when the interface
725                     // is invoked.
726                     fCastOK = true;
727                 }
728             }
729             
730             return fCastOK;
731         }        
732     }
733
734
735     internal class AgileAsyncWorkerItem
736     {
737         private IMethodCallMessage _message;
738         private AsyncResult        _ar;
739         private Object             _target;
740
741         [System.Security.SecurityCritical]  // auto-generated
742         public AgileAsyncWorkerItem(IMethodCallMessage message, AsyncResult ar, Object target)
743         {
744             _message = new MethodCall(message);
745             _ar = ar;
746             _target = target;
747         }
748
749         [System.Security.SecurityCritical]  // auto-generated
750         public static void ThreadPoolCallBack(Object o)
751         {
752             ((AgileAsyncWorkerItem) o).DoAsyncCall();
753         }
754
755
756         [System.Security.SecurityCritical]  // auto-generated
757         public void DoAsyncCall()
758         {
759             (new StackBuilderSink(_target)).AsyncProcessMessage(_message, _ar);
760         }
761     }
762
763 }