Пример #1
0
        public MethodReference GetOrCreateUpdatablePropertyCtor(AssemblyDefinition assembly, TypeReference propertyType)
        {
            if (propertyType.Resolve().IsValueType)
            {
#if true || SILICONSTUDIO_XENKO_XAMARIN_CALLI_BUG
                // Temporary code until Xamarin fixes bugs with generics calli
                // For now, we simply create one class per type T instead of using UpdatableProperty<T>
                // Later, we should only use UpdatableProperty<T> for everything
                var updateEngineType = GetOrCreateUpdateType(assembly, true);
                var updatablePropertyInflatedTypeName = $"UpdatableProperty_{propertyType.ConvertCSharp().Replace('.', '_').Replace("[]", "Array")}";
                var updatablePropertyInflatedType = updateEngineType.NestedTypes.FirstOrDefault(x => x.Name == updatablePropertyInflatedTypeName);
                if (updatablePropertyInflatedType == null)
                {
                    var genericMapping = new Dictionary<TypeReference, TypeReference>();
                    genericMapping.Add(updatablePropertyGenericType.GenericParameters[0], propertyType);

                    updatablePropertyInflatedType = new TypeDefinition(string.Empty, updatablePropertyInflatedTypeName, TypeAttributes.NestedPrivate | TypeAttributes.AutoClass | TypeAttributes.AnsiClass);
                    updateEngineType.NestedTypes.Add(updatablePropertyInflatedType);

                    CecilExtensions.InflateGenericType(updatablePropertyGenericType, updatablePropertyInflatedType, propertyType);
                }

                var updatablePropertyCtor = updatablePropertyInflatedType.Methods.First(x => x.IsConstructor && !x.IsStatic);

                return assembly.MainModule.ImportReference(updatablePropertyCtor);
#else
                return assembly.MainModule.ImportReference(updatablePropertyGenericCtor).MakeGeneric(propertyType);
#endif
            }
            else
            {
                return assembly.MainModule.ImportReference(updatablePropertyObjectGenericCtor).MakeGeneric(propertyType);
            }
        }
Пример #2
0
        public void AddSerializableType(TypeReference dataType, SerializableTypeInfo serializableTypeInfo, string profile = "Default")
        {
            SerializableTypeInfo currentValue;

            // Check if declaring type is generics
            var resolvedType = dataType.Resolve();
            if (resolvedType != null && resolvedType.DeclaringType != null && (resolvedType.HasGenericParameters || resolvedType.DeclaringType.HasGenericParameters))
                throw new NotSupportedException(String.Format("Serialization of nested types referencing parent's generic parameters is not currently supported. " +
                                                              "[Nested type={0} Parent={1}]", resolvedType.FullName, resolvedType.DeclaringType));

            var profileInfo = GetSerializableTypes(profile);

            if (profileInfo.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out currentValue))
            {
                // TODO: Doesn't work in some generic case
                if (//currentValue.SerializerType.ConvertCSharp() != serializableTypeInfo.SerializerType.ConvertCSharp() ||
                    currentValue.Mode != serializableTypeInfo.Mode)
                    throw new InvalidOperationException(string.Format("Incompatible serializer found for same type in different assemblies for {0}", dataType.ConvertCSharp()));
                return;
            }

            // Check that we don't simply try to add the same serializer than Default profile (optimized)
            SerializableTypeInfo defaultValue;
            if (profile != "Default" && SerializableTypes.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out defaultValue))
            {
                if (defaultValue.SerializerType.FullName == serializableTypeInfo.SerializerType.FullName)
                {
                    // Already added in default profile, early exit
                    return;
                }
            }

            profileInfo.AddSerializableTypeInfo(dataType, serializableTypeInfo);

            // Scan and add dependencies (stored in EnumerateGenericInstantiations() functions).
            if (serializableTypeInfo.Local && serializableTypeInfo.SerializerType != null)
            {
                var resolvedSerializerType = serializableTypeInfo.SerializerType.Resolve();
                if (resolvedSerializerType != null)
                {
                    var enumerateGenericInstantiationsMethod = resolvedSerializerType.Methods.FirstOrDefault(x => x.Name == "EnumerateGenericInstantiations");
                    if (enumerateGenericInstantiationsMethod != null)
                    {
                        // Detect all ldtoken (attributes would have been better, but unfortunately C# doesn't allow generics in attributes)
                        foreach (var inst in enumerateGenericInstantiationsMethod.Body.Instructions)
                        {
                            if (inst.OpCode.Code == Code.Ldtoken)
                            {
                                var type = (TypeReference)inst.Operand;

                                // Try to "close" generics type with serializer type as a context
                                var dependentType = ResolveGenericsVisitor.Process(serializableTypeInfo.SerializerType, type);
                                if (!dependentType.ContainsGenericParameter())
                                {
                                    // Import type so that it becomes local to the assembly
                                    // (otherwise SerializableTypeInfo.Local will be false and it won't be instantiated)
                                    var importedType = Assembly.MainModule.ImportReference(dependentType);
                                    if (GenerateSerializer(importedType) == null)
                                    {
                                        throw new InvalidOperationException(string.Format("Could not find serializer for generic dependent type {0} when processing {1}", dependentType, dataType));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }