download delegateserializationholder.cs
Language: C#
Copyright: (c) 2006 Microsoft Corporation. All rights reserved.
LOC: 215
Project Info
Rotor IL Logger(rotorillogger)
Server: CodePlex1
Type: svn
...ger\svn\clr\src\bcl\system\
   __filters.cs
   __hresults.cs
   _localdatastore.cs
   _localdatastoremgr.cs
   ...ssviolationexception.cs
   activationarguments.cs
   activator.cs
   appdomain.cs
   appdomainattributes.cs
   appdomainmanager.cs
   appdomainsetup.cs
   ...ainunloadedexception.cs
   applicationactivator.cs
   applicationexception.cs
   applicationid.cs
   argiterator.cs
   argumentexception.cs
   argumentnullexception.cs
   ...toutofrangeexception.cs
   arithmeticexception.cs
   array.cs
   arraysegment.cs
   ...ypemismatchexception.cs
   asynccallback.cs
   attribute.cs
   attributetargets.cs
   attributeusageattribute.cs
   badimageformatexception.cs
   bcldebug.cs
   bitconverter.cs
   boolean.cs
   buffer.cs
   byte.cs
   ...adappdomainexception.cs
   cfgparser.cs
   char.cs
   charenumerator.cs
   clscompliantattribute.cs
   cominterfaces.cs
   compatibilityflags.cs
   ...usmethodframegeneric.cs
   console.cs
   consolecanceleventargs.cs
   consolespecialkey.cs
   contextboundobject.cs
   contextmarshalexception.cs
   contextstaticattribute.cs
   convert.cs
   currency.cs
   currenttimezone.cs
   datamisalignedexception.cs
   datetime.cs
   datetimekind.cs
   dayofweek.cs
   dbnull.cs
   decimal.cs
   defaultbinder.cs
   delegate.cs
   ...eserializationholder.cs
   dividebyzeroexception.cs
   dllnotfoundexception.cs
   double.cs
   ...ewaitobjectexception.cs
   empty.cs
   ...intnotfoundexception.cs
   enum.cs
   environment.cs
   eventargs.cs
   eventhandler.cs
   exception.cs
   ...utionengineexception.cs
   fieldaccessexception.cs
   flagsattribute.cs
   formatexception.cs
   gc.cs
   guid.cs
   iappdomain.cs
   iappdomainsetup.cs
   iasyncresult.cs
   icloneable.cs
   icomparable.cs
   iconvertible.cs
   icustomformatter.cs
   idisposable.cs
   iequatable.cs
   iformatprovider.cs
   iformattable.cs
   ...xoutofrangeexception.cs
   ...cientmemoryexception.cs
   int16.cs
   int32.cs
   int64.cs
   internal.cs
   intptr.cs
   invalidcastexception.cs
   ...idoperationexception.cs
   invalidprogramexception.cs
   iserviceobjectprovider.cs
   marshalbyrefobject.cs
   math.cs
   mda.cs
   memberaccessexception.cs
   methodaccessexception.cs
   midpointrounding.cs
   missingfieldexception.cs
   missingmemberexception.cs
   missingmethodexception.cs
   multicastdelegate.cs
   ...otsupportedexception.cs
   ndirectmethodframeex.cs
   nonserializedattribute.cs
   ...initenumberexception.cs
   notimplementedexception.cs
   notsupportedexception.cs
   nullable.cs
   nullreferenceexception.cs
   number.cs
   object.cs
   objectdisposedexception.cs
   obsoleteattribute.cs
   oleautbinder.cs
   operatingsystem.cs
   ...ioncanceledexception.cs
   outofmemoryexception.cs
   overflowexception.cs
   paramarrayattribute.cs
   parsenumbers.cs
   platformid.cs
   ...otsupportedexception.cs
   random.cs
   rankexception.cs
   resid.cs
   rttype.cs
   runtimeargumenthandle.cs
   runtimehandles.cs
   sbyte.cs
   serializableattribute.cs
   sharedstatics.cs
   single.cs
   stackoverflowexception.cs
   string.cs
   stringcomparer.cs
   stringcomparison.cs
   stringfreezingattribute.cs
   systemexception.cs
   threadattributes.cs
   threadstaticattribute.cs
   throwhelper.cs
   timeoutexception.cs
   timespan.cs
   timezone.cs
   type.cs
   typecode.cs
   typedreference.cs
   ...tializationexception.cs
   typeloadexception.cs
   typeunloadedexception.cs
   uint16.cs
   uint32.cs
   uint64.cs
   uintptr.cs
   ...rizedaccessexception.cs
   ...edexceptioneventargs.cs
   ...xceptioneventhandler.cs
   ...yserializationholder.cs
   unsafecharbuffer.cs
   valuetype.cs
   variant.cs
   version.cs
   void.cs
   weakreference.cs
   ...gnorememberattribute.cs

// ==++==
// 
//   
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved.
//   
//    The use and distribution terms for this software are contained in the file
//    named license.txt, which can be found in the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by the
//    terms of this license.
//   
//    You must not remove this notice, or any other, from this software.
//   
// 
// ==--==
    
    using System;
    using System.Reflection;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Messaging;
    using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Globalization;

namespace System
{
    [Serializable()]
    internal sealed class DelegateSerializationHolder : IObjectReference, ISerializable
    {
        #region Static Members
        internal static DelegateEntry GetDelegateSerializationInfo(
            SerializationInfo info, Type delegateType, Object target, MethodInfo method, int targetIndex)
        {
            // Used for MulticastDelegate

            if (method == null) 
                throw new ArgumentNullException("method");
    
            if (!method.IsPublic || (method.DeclaringType != null && !method.DeclaringType.IsVisible))
                new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
    
            Type c = delegateType.BaseType;

            if (c == null || (c != typeof(Delegate) && c != typeof(MulticastDelegate)))
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"),"type");

            if (method.DeclaringType == null)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_GlobalMethodSerialization"));

            DelegateEntry de = new DelegateEntry(delegateType.FullName, delegateType.Module.Assembly.FullName, target,
                method.ReflectedType.Module.Assembly.FullName, method.ReflectedType.FullName, method.Name);

            if (info.MemberCount == 0)
            {
                info.SetType(typeof(DelegateSerializationHolder));
                info.AddValue("Delegate",de,typeof(DelegateEntry));
            }

            // target can be an object so it needs to be added to the info, or else a fixup is needed
            // when deserializing, and the fixup will occur too late. If it is added directly to the
            // info then the rules of deserialization will guarantee that it will be available when
            // needed

            if (target != null)
            {
                String targetName = "target" + targetIndex;
                info.AddValue(targetName, de.target);
                de.target = targetName;
            }

            // Due to a number of additions (delegate signature binding relaxation, delegates with open this or closed over the
            // first parameter and delegates over generic methods) we need to send a deal more information than previously. We can
            // get this by serializing the target MethodInfo. We still need to send the same information as before though (the
            // DelegateEntry above) for backwards compatibility. And we want to send the MethodInfo (which is serialized via an
            // ISerializable holder) as a top-level child of the info for the same reason as the target above -- we wouldn't have an
            // order of deserialization guarantee otherwise.
            String methodInfoName = "method" + targetIndex;
            info.AddValue(methodInfoName, method);

            return de;
        }
        #endregion

        #region Definitions
        [Serializable]
        internal class DelegateEntry
        {
            #region Internal Data Members
            internal String type;
            internal String assembly;
            internal Object target;
            internal String targetTypeAssembly;
            internal String targetTypeName;
            internal String methodName;
            internal DelegateEntry delegateEntry;
            #endregion

            #region Constructor
            internal DelegateEntry(
                String type, String assembly, Object target, String targetTypeAssembly, String targetTypeName, String methodName)
            {
                this.type = type;
                this.assembly = assembly;
                this.target = target;
                this.targetTypeAssembly = targetTypeAssembly;
                this.targetTypeName = targetTypeName;
                this.methodName = methodName;
            }
            #endregion

            #region Internal Members
            internal DelegateEntry Entry
            {
                get { return delegateEntry; }
                set { delegateEntry = value; }
            }
            #endregion
        }

        #endregion

		#region Private Data Members
        private DelegateEntry m_delegateEntry;
        private MethodInfo[] m_methods;
		#endregion    
    
        #region Constructor
        private DelegateSerializationHolder(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");
    
            bool bNewWire = true;

            try
            {
                m_delegateEntry = (DelegateEntry)info.GetValue("Delegate", typeof(DelegateEntry));
            }
            catch
            {
                // Old wire format
                m_delegateEntry = OldDelegateWireFormat(info, context);
                bNewWire = false;
            }

            if (bNewWire)
            {
                // retrieve the targets
                DelegateEntry deiter = m_delegateEntry;
                int count = 0;
                while (deiter != null)
                {
                    if (deiter.target != null)
                    {
                        string stringTarget = deiter.target as string; //need test to pass older wire format
                        if (stringTarget != null)
                            deiter.target = info.GetValue(stringTarget, typeof(Object));
                    }
                    count++;
                    deiter = deiter.delegateEntry;
                }

                // If the sender is as recent as us they'll have provided MethodInfos for each delegate. Look for these and pack
                // them into an ordered array if present.
                MethodInfo[] methods = new MethodInfo[count];
                int i;
                for (i = 0; i < count; i++)
                {
                    String methodInfoName = "method" + i;
                    methods[i] = (MethodInfo)info.GetValueNoThrow(methodInfoName, typeof(MethodInfo));
                    if (methods[i] == null)
                        break;
                }

                // If we got the info then make the array available for deserialization.
                if (i == count)
                    m_methods = methods;
            }
        }
        #endregion

        #region Private Members
        private void ThrowInsufficientState(string field)
        {
            throw new SerializationException(
                String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_InsufficientDeserializationState"), field));
        }

        private DelegateEntry OldDelegateWireFormat(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            String delegateType = info.GetString("DelegateType");
            String delegateAssembly = info.GetString("DelegateAssembly");
            Object target = info.GetValue("Target", typeof(Object));
            String targetTypeAssembly = info.GetString("TargetTypeAssembly");
            String targetTypeName = info.GetString("TargetTypeName");
            String methodName = info.GetString("MethodName");

            return new DelegateEntry(delegateType, delegateAssembly, target, targetTypeAssembly, targetTypeName, methodName);
        }

        private Delegate GetDelegate(DelegateEntry de, int index)
        {
            Delegate d;

            try
            {
                if (de.methodName == null || de.methodName.Length == 0)
                    ThrowInsufficientState("MethodName");

                if (de.assembly == null || de.assembly.Length == 0)
                    ThrowInsufficientState("DelegateAssembly");

                if (de.targetTypeName == null || de.targetTypeName.Length == 0)
                    ThrowInsufficientState("TargetTypeName");

                Type type = Assembly.Load(de.assembly).GetType(de.type, true, false);
                Type targetType = Assembly.Load(de.targetTypeAssembly).GetType(de.targetTypeName, true, false);

                // If we received the new style delegate encoding we already have the target MethodInfo in hand.
                if (m_methods != null)
                {
                    Object target = de.target != null ? RemotingServices.CheckCast(de.target, targetType) : null;
                    d = Delegate.InternalCreateDelegate(type, target, m_methods[index]);
                }
                else
                {
                    if (de.target != null)
                        d = Delegate.CreateDelegate(type, RemotingServices.CheckCast(de.target, targetType), de.methodName);
                    else
                        d = Delegate.CreateDelegate(type, targetType, de.methodName);
                }

                if ((d.Method != null && !d.Method.IsPublic) || (d.Method.DeclaringType != null && !d.Method.DeclaringType.IsVisible))
                    new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
            }
            catch (Exception e)
            {
                if (e is SerializationException)
                    throw e;

                throw new SerializationException(e.Message, e);
            }
            catch
            {
                throw new SerializationException();
            }

            return d;
        }
        #endregion

        #region IObjectReference
        public Object GetRealObject(StreamingContext context)
        {
            int count = 0;
            for (DelegateEntry de = m_delegateEntry; de != null; de = de.Entry)
                count++;

            int maxindex = count - 1;

            if (count == 1)
            {
                return GetDelegate(m_delegateEntry, 0);
            }
            else
            {
                object[] invocationList = new object[count];
                
                for (DelegateEntry de = m_delegateEntry; de != null; de = de.Entry)
                {
                    // Be careful to match the index we pass to GetDelegate (used to look up extra information for each delegate) to
                    // the order we process the entries: we're actually looking at them in reverse order.
                    --count;
                    invocationList[count] = GetDelegate(de, maxindex - count);
                }
                return ((MulticastDelegate)invocationList[0]).NewMulticastDelegate(invocationList, invocationList.Length);
            }
        }
        #endregion

        #region ISerializable
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            throw new NotSupportedException(Environment.GetResourceString("NotSupported_DelegateSerHolderSerial"));
        }
        #endregion
    }
}
























About Koders | Resources | Downloads | Support | Black Duck | Submit Project | Terms of Service | DMCA | Privacy Policy | Site Map| Contact Us