internal static Object InternalUnmarshal(
ObjRef objectRef,
Object proxy,
bool fRefine)
{
Object obj = null;
Identity idObj = null;
Context currContext = Thread.CurrentContext;
Message.DebugOut("RemotingServices::InternalUnmarshal: <Begin> Current context id: " + (currContext.ContextID).ToString("x") + "\n");
// This routine can be supplied a custom objref or an objref
// generated by us. We do some sanity checking on the objref
// to make sure that it is valid
if (!ObjRef.IsWellFormed(objectRef))
{
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Argument_BadObjRef"),
"Unmarshal"));
}
// If it is a well known objectRef we need to just connect to
// the URL inside the objectRef.
if (objectRef.IsWellKnown())
{
obj = Unmarshal(
typeof(System.MarshalByRefObject),
objectRef.URI);
// ensure that we cache the objectRef in the ID
// this contains type-info and we need it for
// validating casts on the wellknown proxy
// Note: this code path will be relatively rare ... the case
// when a well known proxy is passed to a remote call
// Otherwise it will be wise to another internal flavor of
// Unmarshal call that returns the identity as an out param.
idObj = IdentityHolder.ResolveIdentity(objectRef.URI);
if (idObj.ObjectRef == null)
{
idObj.RaceSetObjRef(objectRef);
}
return obj;
}
Message.DebugOut("RemotingService::InternalUnmarshal IN URI" + objectRef.URI);
// Get the identity for the URI
idObj = IdentityHolder.FindOrCreateIdentity(objectRef.URI, null, objectRef);
currContext = Thread.CurrentContext;
Message.DebugOut("RemotingServices::Unmarshal: <after FindOrCreateIdentity> Current context id: " +
(currContext.ContextID).ToString("x") + "\n");
// If we successfully completed the above method then we should
// have an identity object
BCLDebug.Assert(null != idObj,"null != idObj");
Message.DebugOut("RemotingService::InternalUnmarshal IN URI" + objectRef.URI);
Message.DebugOut("RemotingServices::InternalUnmarshal: <Begin> Current context id: " +
(currContext.ContextID).ToString("x") + "\n");
// Check whether we are on the server side or client-side
ServerIdentity serverID = idObj as ServerIdentity;
if ( serverID != null )
{
Message.DebugOut("RemotingServices::InternalUnmarshal: Unmarshalling ServerIdentity\n");
// SERVER SIDE
// We are in the app domain of the server object.
// If we are in the same context as the server then
// just return the server object else return the proxy
currContext = Thread.CurrentContext;
Message.DebugOut("RemotingServices::InternalUnmarshal: Current context id: " +
(currContext.ContextID).ToString("x") + "\n");
Message.DebugOut("RemotingServices::InternalUnmarshal: ServerContext id: " +
(serverID.ServerContext.ContextID).ToString("x") + "\n");
if (!serverID.IsContextBound)
{
BCLDebug.Assert(serverID.ServerType.IsMarshalByRef,
"Object must be at least MarshalByRef in order to be marshaled");
if (proxy != null)
{
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Remoting_BadInternalState_ProxySameAppDomain")));
}
obj = serverID.TPOrObject;
}
else
{
Message.DebugOut("RemotingServices::InternalUnmarshal: Contexts don't match, returning proxy\n");
IMessageSink chnlSink = null;
IMessageSink envoySink = null;
// Create the envoy sinks and channel sink
CreateEnvoyAndChannelSinks(
(MarshalByRefObject)serverID.TPOrObject,
null,
out chnlSink,
out envoySink);
// Set the envoy and channel sinks in a thread safe manner
SetEnvoyAndChannelSinks(idObj, chnlSink, envoySink);
// Get or create the proxy and return
obj = GetOrCreateProxy(idObj, proxy, true);
// This will be a TP
BCLDebug.Assert(IsTransparentProxy(obj), "Unexpected naked server");
}
}
else
{
// CLIENT SIDE
Message.DebugOut("RemotingServices::InternalUnmarshal: Unmarshalling Client-side Identity\n");
IMessageSink chnlSink = null;
IMessageSink envoySink = null;
// Create the envoy sinks and channel sink
if (!objectRef.IsObjRefLite())
CreateEnvoyAndChannelSinks(null, objectRef, out chnlSink, out envoySink);
else
CreateEnvoyAndChannelSinks(objectRef.URI, null, out chnlSink, out envoySink);
// Set the envoy and channel sinks in a thread safe manner
SetEnvoyAndChannelSinks(idObj, chnlSink, envoySink);
if (objectRef.HasProxyAttribute())
{
fRefine = true;
}
// Get or create the proxy and return
obj = GetOrCreateProxy(idObj, proxy, fRefine);
}
// Notify TrackingServices that we unmarshaled an object
TrackingServices.UnmarshaledObject(obj, objectRef);
// Return the proxy
Message.DebugOut("RemotingService::InternalUnmarshl OUT \n");
return obj;
}