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; } }
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); }