public XmlFormatClassReaderDelegate GenerateClassReader(ClassDataContract classContract)
{
if (DataContractSerializer.Option == SerializationOption.ReflectionOnly)
{
return new ReflectionXmlClassReader(classContract).ReflectionReadClass;
}
#if NET_NATIVE
else if (DataContractSerializer.Option == SerializationOption.ReflectionAsBackup)
{
return new ReflectionXmlClassReader(classContract).ReflectionReadClass;
}
#endif
else
{
#if NET_NATIVE
throw new InvalidOperationException("Cannot generate class reader");
#else
_ilg = new CodeGenerator();
bool memberAccessFlag = classContract.RequiresMemberAccessForRead(null);
try
{
_ilg.BeginMethod("Read" + classContract.StableName.Name + "FromXml", Globals.TypeOfXmlFormatClassReaderDelegate, memberAccessFlag);
}
catch (SecurityException securityException)
{
if (memberAccessFlag)
{
classContract.RequiresMemberAccessForRead(securityException);
}
else
{
throw;
}
}
InitArgs();
CreateObject(classContract);
_ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal);
InvokeOnDeserializing(classContract);
LocalBuilder objectId = null;
if (classContract.IsISerializable)
{
ReadISerializable(classContract);
}
else
{
ReadClass(classContract);
}
if (Globals.TypeOfIDeserializationCallback.IsAssignableFrom(classContract.UnderlyingType))
{
_ilg.Call(_objectLocal, XmlFormatGeneratorStatics.OnDeserializationMethod, null);
}
InvokeOnDeserialized(classContract);
if (objectId == null)
{
_ilg.Load(_objectLocal);
// Do a conversion back from DateTimeOffsetAdapter to DateTimeOffset after deserialization.
// DateTimeOffsetAdapter is used here for deserialization purposes to bypass the ISerializable implementation
// on DateTimeOffset; which does not work in partial trust.
if (classContract.UnderlyingType == Globals.TypeOfDateTimeOffsetAdapter)
{
_ilg.ConvertValue(_objectLocal.LocalType, Globals.TypeOfDateTimeOffsetAdapter);
_ilg.Call(XmlFormatGeneratorStatics.GetDateTimeOffsetMethod);
_ilg.ConvertValue(Globals.TypeOfDateTimeOffset, _ilg.CurrentMethod.ReturnType);
}
//Copy the KeyValuePairAdapter<K,T> to a KeyValuePair<K,T>.
else if (classContract.IsKeyValuePairAdapter)
{
_ilg.Call(classContract.GetKeyValuePairMethodInfo);
_ilg.ConvertValue(Globals.TypeOfKeyValuePair.MakeGenericType(classContract.KeyValuePairGenericArguments), _ilg.CurrentMethod.ReturnType);
}
else
{
_ilg.ConvertValue(_objectLocal.LocalType, _ilg.CurrentMethod.ReturnType);
}
}
return (XmlFormatClassReaderDelegate)_ilg.EndMethod();
#endif
}
}