Beispiel #1
0
        public override void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model)
        {
            delegateToBaseGetObjectData = VerifyIfBaseImplementsGetObjectData(targetType, model, out var getObjectData);

            // This contributor is going to add a `GetObjectData` method to the proxy type.
            // If a method with the same name and signature exists in the proxied class type,
            // and another contributor has decided to proxy it, we need to tell it not to.
            // Otherwise, we'll end up with two implementations!

            if (getObjectData == null)
            {
                // `VerifyIfBaseImplementsGetObjectData` only searches for `GetObjectData`
                // in the implementation map for `ISerializable`. In the best case, it was
                // already found there. If not, we need to look again, since *any* method
                // with the same signature is a problem.

                var getObjectDataMethod = targetType.GetMethod(
                    "GetObjectData",
                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
                    null,
                    new[] { typeof(SerializationInfo), typeof(StreamingContext) },
                    null);

                if (getObjectDataMethod != null)
                {
                    getObjectData = model.FindMethod(getObjectDataMethod);
                }
            }

            if (getObjectData != null && getObjectData.Proxyable)
            {
                getObjectData.Ignore = true;
            }
        }
Beispiel #2
0
        private bool VerifyIfBaseImplementsGetObjectData(Type baseType, MetaType model, out MetaMethod getObjectData)
        {
            getObjectData = null;

            if (!typeof(ISerializable).IsAssignableFrom(baseType))
            {
                return(false);
            }

            if (baseType.IsDelegateType())
            {
                //working around bug in CLR which returns true for "does this type implement ISerializable" for delegates
                return(false);
            }

            // If base type implements ISerializable, we have to make sure
            // the GetObjectData is marked as virtual
            var getObjectDataMethod = baseType.GetInterfaceMap(typeof(ISerializable)).TargetMethods[0];

            if (getObjectDataMethod.IsPrivate)             //explicit interface implementation
            {
                return(false);
            }

            if (!getObjectDataMethod.IsVirtual || getObjectDataMethod.IsFinal)
            {
                var message = string.Format("The type {0} implements ISerializable, but GetObjectData is not marked as virtual. " +
                                            "Dynamic Proxy needs types implementing ISerializable to mark GetObjectData as virtual " +
                                            "to ensure correct serialization process.",
                                            baseType.FullName);
                throw new ArgumentException(message);
            }

            getObjectData = model.FindMethod(getObjectDataMethod);

            serializationConstructor = baseType.GetConstructor(
                BindingFlags.Instance | BindingFlags.Public |
                BindingFlags.NonPublic,
                null,
                new[] { typeof(SerializationInfo), typeof(StreamingContext) },
                null);

            if (serializationConstructor == null)
            {
                var message = string.Format("The type {0} implements ISerializable, " +
                                            "but failed to provide a deserialization constructor",
                                            baseType.FullName);
                throw new ArgumentException(message);
            }

            return(true);
        }