internal ContentTypeReader[] LoadAssetReaders(ContentReader reader) { // Trick to prevent the linker removing the code, but not actually execute the code if (falseflag) { // Dummy variables required for it to work on iDevices ** DO NOT DELETE ** // This forces the classes not to be optimized out when deploying to iDevices var hByteReader = new ByteReader(); var hSByteReader = new SByteReader(); var hDateTimeReader = new DateTimeReader(); var hDecimalReader = new DecimalReader(); var hBoundingSphereReader = new BoundingSphereReader(); var hBoundingFrustumReader = new BoundingFrustumReader(); var hRayReader = new RayReader(); var hCharListReader = new ListReader <char>(); var hRuneListReader = new ListReader <Rune>(); var hNullableRectReader = new NullableReader <Rectangle>(); var hRectangleArrayReader = new ArrayReader <Rectangle>(); var hRectangleListReader = new ListReader <Rectangle>(); var hVector3ArrayReader = new ArrayReader <Vector3>(); var hVector3ListReader = new ListReader <Vector3>(); var hVector2ArrayReader = new ArrayReader <Vector2>(); var hVector2ListReader = new ListReader <Vector2>(); var hStringListReader = new ListReader <StringReader>(); var hIntListReader = new ListReader <int>(); var hSpriteFontReader = new SpriteFontReader(); var hTexture2DReader = new Texture2DReader(); var hCharReader = new CharReader(); var hRuneReader = new RuneReader(); var hRectangleReader = new RectangleReader(); var hStringReader = new StringReader(); var hVector2Reader = new Vector2Reader(); var hVector3Reader = new Vector3Reader(); var hVector4Reader = new Vector4Reader(); var hCurveReader = new CurveReader(); var hIndexBufferReader = new IndexBufferReader(); var hBoundingBoxReader = new BoundingBoxReader(); var hMatrixReader = new MatrixReader(); var hBasicEffectReader = new BasicEffectReader(); var hVertexBufferReader = new VertexBufferReader(); var hAlphaTestEffectReader = new AlphaTestEffectReader(); var hEnumSpriteEffectsReader = new EnumReader <Graphics.SpriteFlip>(); var hArrayFloatReader = new ArrayReader <float>(); var hArrayMatrixReader = new ArrayReader <Matrix4x4>(); var hEnumBlendReader = new EnumReader <Graphics.Blend>(); var hEffectMaterialReader = new EffectMaterialReader(); var hExternalReferenceReader = new ExternalReferenceReader(); var hSoundEffectReader = new SoundEffectReader(); var hSongReader = new SongReader(); var hModelReader = new ModelReader(); var hInt32Reader = new Int32Reader(); var hEffectReader = new EffectReader(); var hSingleReader = new SingleReader(); // At the moment the Video class doesn't exist // on all platforms... Allow it to compile anyway. #if (IOS && !TVOS) || MONOMAC || (WINDOWS && !OPENGL) || WINDOWS_UAP var hVideoReader = new VideoReader(); #endif } // The first content byte i read tells me the number of content readers in this XNB file var numberOfReaders = reader.Read7BitEncodedInt(); var contentReaders = new ContentTypeReader[numberOfReaders]; var needsInitialize = new BitArray(numberOfReaders); _contentReaders = new Dictionary <Type, ContentTypeReader>(numberOfReaders); // Lock until we're done allocating and initializing any new // content type readers... this ensures we can load content // from multiple threads and still cache the readers. lock (SyncRoot) { // For each reader in the file, // we read out the length of the string which contains the type of the reader, // then we read out the string. // Finally we instantiate an instance of that reader using reflection for (var i = 0; i < numberOfReaders; i++) { // This string tells us what reader we need to decode the following data // string readerTypeString = reader.ReadString(); string originalReaderTypeString = reader.ReadString(); if (ReaderFactories.TryGetValue(originalReaderTypeString, out var readerFactory)) { contentReaders[i] = readerFactory.Invoke(); needsInitialize[i] = true; } else { //System.Diagnostics.Debug.WriteLine(originalReaderTypeString); // Need to resolve namespace differences string readerTypeString = originalReaderTypeString; readerTypeString = PrepareType(readerTypeString); var l_readerType = Type.GetType(readerTypeString); if (l_readerType != null) { if (!ContentReaderCache.TryGetValue(l_readerType, out var typeReader)) { try { typeReader = (ContentTypeReader)l_readerType.GetDefaultConstructor().Invoke(null); } catch (TargetInvocationException ex) { // If you are getting here, the Mono runtime is most likely not able to JIT the type. // In particular, MonoTouch needs help instantiating types // that are only defined in strings in XNB files. throw new InvalidOperationException( $"Failed to get default constructor for {nameof(ContentTypeReader)}. " + $"To work around, add a factory function " + $"(with {nameof(ContentTypeReaderManager)}.{nameof(AddReaderFactory)}) " + "with the following type string: " + originalReaderTypeString, ex); } needsInitialize[i] = true; ContentReaderCache.Add(l_readerType, typeReader); } contentReaders[i] = typeReader; } else { throw new ContentLoadException( $"Could not find {nameof(ContentTypeReader)} Type. " + "Please ensure the name of the assembly " + "that contains the type matches the assembly in the full type name: " + originalReaderTypeString + " (" + readerTypeString + ")"); } } var targetType = contentReaders[i].TargetType; if (targetType != null) { if (!_contentReaders.ContainsKey(targetType)) { _contentReaders.Add(targetType, contentReaders[i]); } } // I think the next 4 bytes refer to the "Version" of the type reader, // although it always seems to be zero reader.ReadInt32(); } // Initialize any new readers. for (int i = 0; i < contentReaders.Length; i++) { if (needsInitialize.Get(i)) { contentReaders[i].Initialize(this); } } } return(contentReaders); }
private static ReadElement GetElementReader(ContentTypeReaderManager manager, MemberInfo member) { var property = member as PropertyInfo; var field = member as FieldInfo; Debug.Assert(field != null && property != null); if (property != null) { // Properties must have at least a getter. if (!property.CanRead) { return(null); } // Skip over indexer properties. if (property.GetIndexParameters().Any()) { return(null); } } // Are we explicitly asked to ignore this item? if (member.GetCustomAttribute <ContentSerializerIgnoreAttribute>() != null) { return(null); } var contentSerializerAttribute = member.GetCustomAttribute <ContentSerializerAttribute>(); if (contentSerializerAttribute == null) { if (property != null) { // There is no ContentSerializerAttribute, so non-public // properties cannot be deserialized. if (!ReflectionHelpers.PropertyIsPublic(property)) { return(null); } // If the read-only property has a type reader, // and CanDeserializeIntoExistingObject is true, // then it is safe to deserialize into the existing object. if (!property.CanWrite) { var typeReader = manager.GetTypeReader(property.PropertyType); if (typeReader == null || !typeReader.CanDeserializeIntoExistingObject) { return(null); } } } else { // There is no ContentSerializerAttribute, so non-public // fields cannot be deserialized. if (!field.IsPublic) { return(null); } // evolutional: Added check to skip initialise only fields if (field.IsInitOnly) { return(null); } } } Type elementType; Action <object, object> setter; if (property != null) { elementType = property.PropertyType; if (property.CanWrite) { setter = (o, v) => property.SetValue(o, v, null); } else { setter = (o, v) => { } }; } else { elementType = field.FieldType; setter = field.SetValue; } // Shared resources get special treatment. if (contentSerializerAttribute != null && contentSerializerAttribute.SharedResource) { return((input, parent) => { input.ReadSharedResource <object>((value) => setter(parent, value)); }); } // We need to have a reader at this point. var reader = manager.GetTypeReader(elementType); if (reader == null) { if (elementType == typeof(Array)) { reader = new ArrayReader <Array>(); } else { throw new ContentLoadException( $"Content reader could not be found for {elementType.FullName} type."); } } // We use the construct delegate to pick the correct existing // object to be the target of deserialization. Func <object, object> construct = parent => null; if (property != null && !property.CanWrite) { construct = parent => property.GetValue(parent, null); } return((input, parent) => { var existing = construct.Invoke(parent); var obj2 = input.ReadObject(reader, existing); setter(parent, obj2); }); }