コード例 #1
0
        public static TypeReference MakeGeneric(this TypeReference self, params TypeReference[] arguments)
        {
            if (self.GenericParameters.Count != arguments.Length)
                throw new ArgumentException($"generic parameters count of type {self.Name} does not match given number of types");

            var instance = new GenericInstanceType(self);
            foreach (var argument in arguments)
                instance.GenericArguments.Add(argument);

            return instance;
        }
コード例 #2
0
ファイル: TypeReferenceRocks.cs プロジェクト: ttRevan/cecil
        public static GenericInstanceType MakeGenericInstanceType(this TypeReference self, params TypeReference [] arguments)
        {
            if (self == null)
                throw new ArgumentNullException ("self");
            if (arguments == null)
                throw new ArgumentNullException ("arguments");
            if (arguments.Length == 0)
                throw new ArgumentException ();
            if (self.GenericParameters.Count != arguments.Length)
                throw new ArgumentException ();

            var instance = new GenericInstanceType (self);

            foreach (var argument in arguments)
                instance.GenericArguments.Add (argument);

            return instance;
        }
コード例 #3
0
 public static void Accept(this GenericInstanceType genericInstanceType, Unity.Cecil.Visitor.Visitor visitor)
 {
     genericInstanceType.DoAccept <GenericInstanceType>(visitor);
 }
コード例 #4
0
 public TypeResolver(GenericInstanceType typeDefinitionContext, GenericInstanceMethod methodDefinitionContext)
 {
     m_TypeDefinitionContext   = typeDefinitionContext;
     m_MethodDefinitionContext = methodDefinitionContext;
 }
コード例 #5
0
 public TypeResolver(GenericInstanceType typeDefinitionContext)
 {
     m_TypeDefinitionContext = typeDefinitionContext;
 }
コード例 #6
0
        public static bool IsFieldTypeSerializable(TypeReference type, IReadOnlyDictionary <GenericParameter, TypeReference> arguments)
        {
            // if it's generic parameter then get its real type
            if (type.IsGenericParameter)
            {
                GenericParameter parameter = (GenericParameter)type;
                type = arguments[parameter];
            }

            if (type.IsArray)
            {
                ArrayType array = (ArrayType)type;
                // one dimention array only
                if (!array.IsVector)
                {
                    return(false);
                }

                // if it's generic parameter then get its real type
                TypeReference elementType = array.ElementType;
                if (elementType.IsGenericParameter)
                {
                    GenericParameter parameter = (GenericParameter)elementType;
                    elementType = arguments[parameter];
                }

                // array of arrays isn't serializable
                if (elementType.IsArray)
                {
                    return(false);
                }
                // array of lists isn't serializable
                if (MonoType.IsList(elementType))
                {
                    return(false);
                }
                // check if element is serializable
                return(IsFieldTypeSerializable(elementType, arguments));
            }

            if (MonoType.IsList(type))
            {
                // list is serialized same way as array, so check its argument
                GenericInstanceType list        = (GenericInstanceType)type;
                TypeReference       listElement = list.GenericArguments[0];

                // if it's generic parameter then get its real type
                if (listElement.IsGenericParameter)
                {
                    GenericParameter parameter = (GenericParameter)listElement;
                    listElement = arguments[parameter];
                }

                // list of arrays isn't serializable
                if (listElement.IsArray)
                {
                    return(false);
                }
                // list of lists isn't serializable
                if (MonoType.IsList(listElement))
                {
                    return(false);
                }
                // check if element is serializable
                return(IsFieldTypeSerializable(listElement, arguments));
            }

            if (type.IsPrimitive)
            {
                return(true);
            }
            if (MonoType.IsString(type))
            {
                return(true);
            }
            if (MonoType.IsEngineStruct(type))
            {
                return(true);
            }
            if (MonoType.IsEnginePointer(type))
            {
                return(true);
            }

            if (type.IsGenericInstance)
            {
                return(false);
            }
            if (MonoType.IsObject(type))
            {
                return(false);
            }

            TypeDefinition definition = type.Resolve();

            if (definition.IsInterface)
            {
                return(false);
            }
            if (MonoType.IsCompilerGenerated(definition))
            {
                return(false);
            }
            if (definition.IsSerializable)
            {
                return(true);
            }
            if (definition.IsEnum)
            {
                return(true);
            }

            return(false);
        }
コード例 #7
0
        // for [SyncVar] health, weaver generates
        //
        //   NetworkHealth
        //   {
        //      get => health;
        //      set => GeneratedSyncVarSetter(...)
        //   }
        //
        // the setter used to be manually IL generated, but we moved it to C# :)
        public MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDefinition fd, string originalName, long dirtyBit, FieldDefinition netFieldId, ref bool WeavingFailed)
        {
            //Create the set method
            MethodDefinition set = new MethodDefinition($"set_Network{originalName}", MethodAttributes.Public |
                                                        MethodAttributes.SpecialName |
                                                        MethodAttributes.HideBySig,
                                                        weaverTypes.Import(typeof(void)));

            ILProcessor worker = set.Body.GetILProcessor();

            // if (!SyncVarEqual(value, ref playerData))
            Instruction endOfMethod = worker.Create(OpCodes.Nop);

            // NOTE: SyncVar...Equal functions are static.
            // don't Emit Ldarg_0 aka 'this'.

            // call WeaverSyncVarSetter<T>(T value, ref T field, ulong dirtyBit, Action<T, T> OnChanged = null)
            //   IL_0000: ldarg.0
            //   IL_0001: ldarg.1
            //   IL_0002: ldarg.0
            //   IL_0003: ldflda int32 Mirror.Examples.Tanks.Tank::health
            //   IL_0008: ldc.i4.1
            //   IL_0009: conv.i8
            //   IL_000a: ldnull
            //   IL_000b: call instance void [Mirror]Mirror.NetworkBehaviour::GeneratedSyncVarSetter<int32>(!!0, !!0&, uint64, class [netstandard]System.Action`2<!!0, !!0>)
            //   IL_0010: ret

            // 'this.' for the call
            worker.Emit(OpCodes.Ldarg_0);

            // first push 'value'
            worker.Emit(OpCodes.Ldarg_1);

            // push 'ref T this.field'
            worker.Emit(OpCodes.Ldarg_0);
            worker.Emit(OpCodes.Ldflda, fd);

            // push the dirty bit for this SyncVar
            worker.Emit(OpCodes.Ldc_I8, dirtyBit);

            // hook?
            MethodDefinition hookMethod = GetHookMethod(td, fd, ref WeavingFailed);

            if (hookMethod != null)
            {
                // IL_000a: ldarg.0
                // IL_000b: ldftn instance void Mirror.Examples.Tanks.Tank::ExampleHook(int32, int32)
                // IL_0011: newobj instance void class [netstandard]System.Action`2<int32, int32>::.ctor(object, native int)

                // this.
                worker.Emit(OpCodes.Ldarg_0);

                // the function
                worker.Emit(OpCodes.Ldftn, hookMethod);

                // call 'new Action<T,T>()' constructor to convert the function to an action
                // we need to make an instance of the generic Action<T,T>.
                //
                // TODO this allocates a new 'Action' for every SyncVar hook call.
                //      we should allocate it once and store it somewhere in the future.
                //      hooks are only called on the client though, so it's not too bad for now.
                TypeReference       actionRef       = assembly.MainModule.ImportReference(typeof(Action <,>));
                GenericInstanceType genericInstance = actionRef.MakeGenericInstanceType(fd.FieldType, fd.FieldType);
                worker.Emit(OpCodes.Newobj, weaverTypes.ActionT_T.MakeHostInstanceGeneric(assembly.MainModule, genericInstance));
            }
            // pass 'null' as hook
            else
            {
                worker.Emit(OpCodes.Ldnull);
            }

            // call GeneratedSyncVarSetter<T>.
            // special cases for GameObject/NetworkIdentity/NetworkBehaviour
            // passing netId too for persistence.
            if (fd.FieldType.Is <UnityEngine.GameObject>())
            {
                // GameObject setter needs one more parameter: netId field ref
                worker.Emit(OpCodes.Ldarg_0);
                worker.Emit(OpCodes.Ldflda, netFieldId);
                worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarSetter_GameObject);
            }
            else if (fd.FieldType.Is <NetworkIdentity>())
            {
                // NetworkIdentity setter needs one more parameter: netId field ref
                worker.Emit(OpCodes.Ldarg_0);
                worker.Emit(OpCodes.Ldflda, netFieldId);
                worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarSetter_NetworkIdentity);
            }
            // TODO this only uses the persistent netId for types DERIVED FROM NB.
            //      not if the type is just 'NetworkBehaviour'.
            //      this is what original implementation did too. fix it after.
            else if (fd.FieldType.IsDerivedFrom <NetworkBehaviour>())
            {
                // NetworkIdentity setter needs one more parameter: netId field ref
                // (actually its a NetworkBehaviourSyncVar type)
                worker.Emit(OpCodes.Ldarg_0);
                worker.Emit(OpCodes.Ldflda, netFieldId);
                // make generic version of GeneratedSyncVarSetter_NetworkBehaviour<T>
                MethodReference getFunc = weaverTypes.generatedSyncVarSetter_NetworkBehaviour_T.MakeGeneric(assembly.MainModule, fd.FieldType);
                worker.Emit(OpCodes.Call, getFunc);
            }
            else
            {
                // make generic version of GeneratedSyncVarSetter<T>
                MethodReference generic = weaverTypes.generatedSyncVarSetter.MakeGeneric(assembly.MainModule, fd.FieldType);
                worker.Emit(OpCodes.Call, generic);
            }

            worker.Append(endOfMethod);

            worker.Emit(OpCodes.Ret);

            set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType));
            set.SemanticsAttributes = MethodSemanticsAttributes.Setter;

            return(set);
        }
コード例 #8
0
        static bool CompareTypes(TypeReference iType, TypeReference tType)
        {
            if (iType.IsGenericParameter)
            {
                return(true);
            }

            if (iType.IsArray)
            {
                if (!tType.IsArray)
                {
                    return(false);
                }
                return(CompareTypes(iType.GetElementType(), tType.GetElementType()));
            }

            if (iType.IsByReference)
            {
                if (!tType.IsByReference)
                {
                    return(false);
                }
                return(CompareTypes(iType.GetElementType(), tType.GetElementType()));
            }

            if (iType.Name != tType.Name)
            {
                return(false);
            }

            if (iType.Namespace != tType.Namespace)
            {
                return(false);
            }

            TypeDefinition iTypeDef = iType.Resolve();

            if (iTypeDef == null)
            {
                return(false);
            }

            TypeDefinition tTypeDef = tType.Resolve();

            if (tTypeDef == null)
            {
                return(false);
            }

            if (iTypeDef.Module.FullyQualifiedName != tTypeDef.Module.FullyQualifiedName)
            {
                return(false);
            }

            if (iType is Mono.Cecil.GenericInstanceType && tType is Mono.Cecil.GenericInstanceType)
            {
                GenericInstanceType iGType = iType as GenericInstanceType;
                GenericInstanceType tGType = tType as GenericInstanceType;

                if (iGType.GenericArguments.Count != tGType.GenericArguments.Count)
                {
                    return(false);
                }
                for (int i = 0; i < iGType.GenericArguments.Count; i++)
                {
                    if (iGType.GenericArguments [i].IsGenericParameter)
                    {
                        continue;
                    }
                    if (!CompareTypes(iGType.GenericArguments [i], tGType.GenericArguments [i]))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
コード例 #9
0
ファイル: Readers.cs プロジェクト: lexnewgate/Mirror
        static MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable, int recursionCount)
        {
            GenericInstanceType genericInstance = (GenericInstanceType)variable;
            TypeReference       elementType     = genericInstance.GenericArguments[0];

            MethodReference elementReadFunc = GetReadFunc(elementType, recursionCount + 1);

            if (elementReadFunc == null)
            {
                return(null);
            }

            string functionName = "_ReadArraySegment_" + variable.GetElementType().Name + "_";

            if (variable.DeclaringType != null)
            {
                functionName += variable.DeclaringType.Name;
            }
            else
            {
                functionName += "None";
            }

            // create new reader for this type
            MethodDefinition readerFunc = new MethodDefinition(functionName,
                                                               MethodAttributes.Public |
                                                               MethodAttributes.Static |
                                                               MethodAttributes.HideBySig,
                                                               variable);

            readerFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));

            // int lengh
            readerFunc.Body.Variables.Add(new VariableDefinition(Weaver.int32Type));
            // T[] array
            readerFunc.Body.Variables.Add(new VariableDefinition(elementType.MakeArrayType()));
            // int i;
            readerFunc.Body.Variables.Add(new VariableDefinition(Weaver.int32Type));
            readerFunc.Body.InitLocals = true;

            ILProcessor worker = readerFunc.Body.GetILProcessor();

            // int length = reader.ReadPackedInt32();
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Call, GetReadFunc(Weaver.int32Type)));
            worker.Append(worker.Create(OpCodes.Stloc_0));

            // T[] array = new int[length]
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Newarr, elementType));
            worker.Append(worker.Create(OpCodes.Stloc_1));


            // loop through array and deserialize each element
            // generates code like this
            // for (int i=0; i< length ; i++)
            // {
            //     value[i] = reader.ReadXXX();
            // }
            worker.Append(worker.Create(OpCodes.Ldc_I4_0));
            worker.Append(worker.Create(OpCodes.Stloc_2));
            Instruction labelHead = worker.Create(OpCodes.Nop);

            worker.Append(worker.Create(OpCodes.Br, labelHead));

            // loop body
            Instruction labelBody = worker.Create(OpCodes.Nop);

            worker.Append(labelBody);
            {
                // value[i] = reader.ReadT();
                worker.Append(worker.Create(OpCodes.Ldloc_1));
                worker.Append(worker.Create(OpCodes.Ldloc_2));
                worker.Append(worker.Create(OpCodes.Ldelema, elementType));
                worker.Append(worker.Create(OpCodes.Ldarg_0));
                worker.Append(worker.Create(OpCodes.Call, elementReadFunc));
                worker.Append(worker.Create(OpCodes.Stobj, elementType));
            }

            worker.Append(worker.Create(OpCodes.Ldloc_2));
            worker.Append(worker.Create(OpCodes.Ldc_I4_1));
            worker.Append(worker.Create(OpCodes.Add));
            worker.Append(worker.Create(OpCodes.Stloc_2));

            // loop while check
            worker.Append(labelHead);
            worker.Append(worker.Create(OpCodes.Ldloc_2));
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Blt, labelBody));

            // return new ArraySegment<T>(array);
            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Newobj, Weaver.ArraySegmentConstructorReference.MakeHostInstanceGeneric(genericInstance)));
            worker.Append(worker.Create(OpCodes.Ret));
            return(readerFunc);
        }
コード例 #10
0
        public void Execute()
        {
            var reactiveUI     = ModuleDefinition.AssemblyReferences.Where(x => x.Name == "ReactiveUI").OrderByDescending(x => x.Version).FirstOrDefault();
            var helpers        = ModuleDefinition.AssemblyReferences.Where(x => x.Name == "Reactive.Fody.Helpers").OrderByDescending(x => x.Version).FirstOrDefault();
            var reactiveObject = new TypeReference("ReactiveUI", "IReactiveObject", ModuleDefinition, reactiveUI);

            var targetTypes = ModuleDefinition.GetAllTypes().Where(x => x.BaseType != null && reactiveObject.IsAssignableFrom(x.BaseType)).ToArray();

            var reactivePropertyExtensions = ModuleDefinition.FindType("Reactive.Fody.Helpers", "ReactivePropertyExtensions", helpers).Resolve();

            if (reactivePropertyExtensions == null)
            {
                throw new Exception("reactivePropertyExtensions is null");
            }

            var raiseAndSetIfChangedMethod = ModuleDefinition.ImportReference(reactivePropertyExtensions.Methods.Single(x => x.Name == "RaiseAndSetIfChanged"));

            if (raiseAndSetIfChangedMethod == null)
            {
                throw new Exception("raiseAndSetIfChangedMethod is null");
            }

            var reactiveAttribute = ModuleDefinition.FindType("Reactive.Fody.Helpers", "ReactiveAttribute", helpers);

            if (reactiveAttribute == null)
            {
                throw new Exception("reactiveAttribute is null");
            }

            var reactiveObjectExtensions = new TypeReference("ReactiveUI", "IReactiveObjectExtensions", ModuleDefinition, reactiveUI).Resolve();

            if (reactiveObjectExtensions == null)
            {
                throw new Exception("reactiveObjectExtensions is null");
            }

            var raisePropertyChangedMethod = ModuleDefinition.ImportReference(reactiveObjectExtensions.Methods.Single(x => x.Name == "RaisePropertyChanged"));

            if (raisePropertyChangedMethod == null)
            {
                throw new Exception("raisePropertyChangedMethod is null");
            }

            foreach (var targetType in targetTypes)
            {
                var setMethodByGetMethods = targetType.Properties
                                            .Where(x => x.SetMethod != null && x.GetMethod != null && x.IsDefined(reactiveAttribute))
                                            .ToDictionary(x => x.GetMethod, x => x.SetMethod);

                foreach (var property in targetType.Properties.Where(x => x.IsDefined(reactiveAttribute)).ToArray())
                {
                    TypeReference genericTargetType = targetType;
                    if (targetType.HasGenericParameters)
                    {
                        var genericDeclaration = new GenericInstanceType(targetType);
                        foreach (var parameter in targetType.GenericParameters)
                        {
                            genericDeclaration.GenericArguments.Add(parameter);
                        }
                        genericTargetType = genericDeclaration;
                    }

                    MethodDefinition[] getMethods;
                    if (property.SetMethod == null && property.GetMethod.TryGetMethodDependencies(out getMethods))
                    {
                        var setMethodsForGetInstructions = getMethods
                                                           .Where(x => setMethodByGetMethods.ContainsKey(x))
                                                           .Select(x => setMethodByGetMethods[x])
                                                           .ToArray();

                        if (!setMethodsForGetInstructions.Any())
                        {
                            LogError($"Get only Property {property.DeclaringType.FullName}.{property.Name} has no supported dependent properties. " +
                                     $"Only dependent auto properties decorated with the [Reactive] attribute can be weaved to raise property change on {property.Name}");
                        }

                        var raisePropertyChangedMethodReference = raisePropertyChangedMethod.MakeGenericMethod(genericTargetType);

                        foreach (var method in setMethodsForGetInstructions)
                        {
                            method.Body.Emit(il =>
                            {
                                var last = method.Body.Instructions.Last(i => i.OpCode == OpCodes.Ret);
                                il.InsertBefore(last, il.Create(OpCodes.Ldarg_0));
                                il.InsertBefore(last, il.Create(OpCodes.Ldstr, property.Name));
                                il.InsertBefore(last, il.Create(OpCodes.Call, raisePropertyChangedMethodReference));
                            });
                        }

                        // Move on to next property for the target type
                        continue;
                    }

                    if (property.SetMethod == null)
                    {
                        LogError($"Property {property.DeclaringType.FullName}.{property.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [Reactive]");
                        continue;
                    }

                    // Declare a field to store the property value
                    var field = new FieldDefinition("$" + property.Name, FieldAttributes.Private, property.PropertyType);
                    targetType.Fields.Add(field);

                    // Remove old field (the generated backing field for the auto property)
                    var oldField           = (FieldReference)property.GetMethod.Body.Instructions.Where(x => x.Operand is FieldReference).Single().Operand;
                    var oldFieldDefinition = oldField.Resolve();
                    targetType.Fields.Remove(oldFieldDefinition);

                    // See if there exists an initializer for the auto-property
                    var constructors = targetType.Methods.Where(x => x.IsConstructor);
                    foreach (var constructor in constructors)
                    {
                        var fieldAssignment = constructor.Body.Instructions.SingleOrDefault(x => Equals(x.Operand, oldFieldDefinition) || Equals(x.Operand, oldField));
                        if (fieldAssignment != null)
                        {
                            // Replace field assignment with a property set (the stack semantics are the same for both,
                            // so happily we don't have to manipulate the bytecode any further.)
                            var setterCall = constructor.Body.GetILProcessor().Create(property.SetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, property.SetMethod);
                            constructor.Body.GetILProcessor().Replace(fieldAssignment, setterCall);
                        }
                    }

                    // Build out the getter which simply returns the value of the generated field
                    property.GetMethod.Body = new MethodBody(property.GetMethod);
                    property.GetMethod.Body.Emit(il =>
                    {
                        il.Emit(OpCodes.Ldarg_0);                                   // this
                        il.Emit(OpCodes.Ldfld, field.BindDefinition(targetType));   // pop -> this.$PropertyName
                        il.Emit(OpCodes.Ret);                                       // Return the field value that is lying on the stack
                    });

                    var methodReference = raiseAndSetIfChangedMethod.MakeGenericMethod(genericTargetType, property.PropertyType);

                    // Build out the setter which fires the RaiseAndSetIfChanged method
                    if (property.SetMethod == null)
                    {
                        throw new Exception("[Reactive] is decorating " + property.DeclaringType.FullName + "." + property.Name + ", but the property has no setter so there would be nothing to react to.  Consider removing the attribute.");
                    }
                    property.SetMethod.Body = new MethodBody(property.SetMethod);
                    property.SetMethod.Body.Emit(il =>
                    {
                        RaiseAndSetIfChanged(methodReference, targetType, field, il, property.Name);
                    });
                }
            }
        }
コード例 #11
0
 private static string NonUniqueShortNameFor(GenericInstanceType type) =>
 (NonUniqueShortNameFor(type.ElementType) + "_gen");
コード例 #12
0
        static void ProcessMethod(MethodDefinition method, HashSet <TypeReference> typeset)
        {
            // this is needed in case we return an enum, a struct or something mapped
            // to p/invoke (i.e. no ctor called). We also need to check for arrays.
            TypeReference t = method.ReturnType;

            AddType(typeset, t);

            if (method.HasParameters)
            {
                // an "out" from a p/invoke must be flagged
                foreach (ParameterDefinition parameter in method.Parameters)
                {
                    // we don't want the reference (&) on the type
                    t = parameter.ParameterType.GetElementType();
                    AddType(typeset, t);
                }
            }

            if (!method.HasBody)
            {
                return;
            }

            MethodBody body = method.Body;

            if (body.HasVariables)
            {
                // add every type of variables we use
                foreach (VariableDefinition variable in body.Variables)
                {
                    t = variable.VariableType;
                    AddType(typeset, t);
                }
            }

            // add every type we create or refer to (e.g. loading fields from an enum)
            foreach (Instruction ins in body.Instructions)
            {
                if (ins.Operand == null)
                {
                    continue;
                }

                t = ins.Operand as TypeReference;
                if (t == null)
                {
                    MethodReference m = ins.Operand as MethodReference;
                    if (m != null)
                    {
                        t = m.DeclaringType;
                        GenericInstanceType generic = (t as GenericInstanceType);
                        if (generic != null)
                        {
                            t = generic.GetElementType();
                        }
                    }
                    else
                    {
                        FieldReference f = ins.Operand as FieldReference;
                        if (f != null)
                        {
                            t = f.DeclaringType;
                        }
                    }
                }

                if (t != null)
                {
                    AddType(typeset, t);
                }
            }
        }
コード例 #13
0
        private static void GenerateNormal(MethodDefinition method, TypeReference enumerable, GenericInstanceType selector, GenericInstanceType func)
        {
            method.Parameters.Add(new ParameterDefinition("@this", ParameterAttributes.In, new ByReferenceType(enumerable))
            {
                CustomAttributes = { Helper.GetSystemRuntimeCompilerServicesIsReadOnlyAttributeTypeReference() }
            });
            method.Parameters.Add(new ParameterDefinition("selector", ParameterAttributes.None, func));

            var body = method.Body;

            body.Variables.Add(new VariableDefinition(selector));

            body.GetILProcessor()

            .LoadFuncArgumentAndStoreToLocalVariableField(1, 0)

            .LdArg(0)
            .LdLocA(0)
            .NewObj(method.ReturnType.FindMethod(".ctor", 2))
            .Ret();
        }
コード例 #14
0
        private static void GenerateSpecial(MethodDefinition method, TypeReference baseEnumerable, GenericInstanceType enumerable, GenericInstanceType selector, GenericInstanceType func)
        {
            method.Parameters.Add(new ParameterDefinition("@this", ParameterAttributes.None, baseEnumerable));
            method.Parameters.Add(new ParameterDefinition("selector", ParameterAttributes.None, func));

            var body = method.Body;

            body.InitLocals = true;
            body.Variables.Add(new VariableDefinition(enumerable));
            body.Variables.Add(new VariableDefinition(selector));

            body.GetILProcessor()
            .LdLocA(0)
            .LdArg(0)
            .Call(enumerable.FindMethod(".ctor", 1))

            .LoadFuncArgumentAndStoreToLocalVariableField(1, 1)

            .LdLocA(0)
            .LdLocA(1)
            .NewObj(method.ReturnType.FindMethod(".ctor", 2))
            .Ret();
        }
コード例 #15
0
 /// <summary>
 /// This method resolves a type. This method ignores the methods and fields. You have to
 /// resolve them manually.
 /// </summary>
 /// <param name="hostModule">The module in which the changes are made.</param>
 /// <param name="type">The type to resolve.</param>
 /// <param name="AddedClasses">Newly added classes to lookup while resolving.</param>
 /// <param name="TypesMap">A map of types to lookup while resolving.</param>
 /// <returns></returns>
 protected static TypeReference Resolve(
     ModuleDefinition hostModule,
     TypeReference type,
     Dictionary <TypeReference, TypeDefinition> AddedClasses,
     Dictionary <TypeReference, TypeReference> TypesMap)
 {
     if (type is GenericInstanceType)
     {
         GenericInstanceType gType = (GenericInstanceType)type;
         GenericInstanceType nType = new GenericInstanceType(Resolve(hostModule, gType.ElementType, AddedClasses, TypesMap));
         foreach (TypeReference t in gType.GenericArguments)
         {
             nType.GenericArguments.Add(Resolve(hostModule, t, AddedClasses, TypesMap));
         }
         return(nType);
     }
     if (type == null || type is GenericParameter || (type.IsArray && type.GetElementType() is GenericParameter))
     {
         return(type);
     }
     if (TypesMap.ContainsKey(type))
     {
         return(hostModule.Import(TypesMap[type]));
     }
     foreach (TypeReference addedType in AddedClasses.Keys)
     {
         if (addedType == type)
         {
             return(hostModule.Import(AddedClasses[addedType]));
         }
     }
     if (type.Module != hostModule)
     {
         TypeDefinition t = hostModule.GetType(type.FullName);
         if (t != null)
         {
             return((TypeReference)t);
         }
         if (hostModule == null || type == null)
         {
             return(type);
         }
         else
         {
             try
             {
                 return(hostModule.Import(type));
             }
             catch (Exception e)
             {
                 System.Console.WriteLine(type.GetElementType());
                 System.Console.WriteLine(type.GetType().FullName);
                 throw e;
             }
         }
     }
     else
     {
         return(type);
     }
 }
コード例 #16
0
        internal static TypeReference ResolveType(TypeReference original, Mono.Collections.Generic.Collection<GenericParameter> parameters, Mono.Collections.Generic.Collection<TypeReference> arguments)
        {
            TypeSpecification spec = original as TypeSpecification;
            ArrayType array = original as ArrayType;
            ByReferenceType reference = original as ByReferenceType;
            GenericInstanceType genericType = original as GenericInstanceType;

            if (parameters.Count != arguments.Count)
                throw new System.ArgumentException ("Parameters and Arguments must have the same number of elements.");

            if (spec != null) {
                TypeReference resolved = ResolveType (spec.ElementType, parameters, arguments);

                if (genericType != null) {
                    GenericInstanceType result = new GenericInstanceType (genericType.ElementType);
                    bool found;
                    for (int i = 0; i < genericType.ElementType.GenericParameters.Count; i++) {
                        found = false;
                        for (int k = 0; k < parameters.Count; k++) {
                            if (genericType.ElementType.GenericParameters [i].Name == parameters [k].Name) {
                                found = true;
                                result.GenericArguments.Add (arguments [k]);
                                break;
                            }
                        }
                        if (!found)
                            result.GenericArguments.Add (genericType.ElementType.GenericParameters [i]);
                    }
                    return result;
                }

                if (resolved == spec.ElementType)
                    return spec;

                if (array != null) {
                    return new ArrayType (resolved, array.Dimensions.Count);
                } else if (reference != null) {
                    return new ByReferenceType (resolved);
                } else {
                    throw new System.NotImplementedException ();
                }
            } else {
                for (int i = 0; i < parameters.Count; i++) {
                    if (parameters [i] == original) {
                        return arguments [i];
                    }
                }
                return original;
            }
        }
コード例 #17
0
        public static bool ExpandPositionalGenericParameters(TypeReference type, out TypeReference expanded)
        {
            var gp    = type as GenericParameter;
            var git   = type as GenericInstanceType;
            var at    = type as ArrayType;
            var byref = type as ByReferenceType;

            TypeReference _expanded;

            if (gp != null)
            {
                if (IsPositionalGenericParameter(gp))
                {
                    var ownerType   = gp.Owner as TypeReference;
                    var ownerMethod = gp.Owner as MethodReference;

                    if (ownerType != null)
                    {
                        var resolvedOwnerType = ownerType.Resolve();
                        if (resolvedOwnerType == null)
                        {
                            expanded = type;
                            return(false);
                        }

                        expanded = resolvedOwnerType.GenericParameters[int.Parse(gp.Name.Replace("!", ""))];
                        return(true);
                    }
                    else if (ownerMethod != null)
                    {
                        var resolvedOwnerMethod = ownerMethod.Resolve();
                        if (resolvedOwnerMethod == null)
                        {
                            expanded = type;
                            return(false);
                        }

                        expanded = resolvedOwnerMethod.GenericParameters[int.Parse(gp.Name.Replace("!", ""))];
                        return(true);
                    }
                    else
                    {
                        throw new NotImplementedException("Unknown positional generic parameter type");
                    }
                }
            }

            if (git != null)
            {
                var elt = git.ElementType;

                if (ContainsPositionalGenericParameter(elt) || git.GenericArguments.Any(ContainsPositionalGenericParameter))
                {
                    ExpandPositionalGenericParameters(elt, out _expanded);
                    var result = new GenericInstanceType(_expanded);

                    foreach (var ga in git.GenericArguments)
                    {
                        ExpandPositionalGenericParameters(ga, out _expanded);
                        result.GenericArguments.Add(_expanded);
                    }

                    expanded = result;
                    return(true);
                }
            }

            if (at != null)
            {
                ExpandPositionalGenericParameters(at.ElementType, out _expanded);
            }

            if (byref != null)
            {
                ExpandPositionalGenericParameters(byref.ElementType, out _expanded);
            }

            expanded = type;
            return(false);
        }
コード例 #18
0
        void InitializeBaseType()
        {
            if (definition != null && definition.BaseType != null)
            {
                bool       specialProcess = false;
                List <int> spIdx          = null;
                if (definition.BaseType.IsGenericInstance)
                {
                    GenericInstanceType git = definition.BaseType as GenericInstanceType;
                    var elementType         = appdomain.GetType(git.ElementType, this, null);
                    if (elementType is CLRType)
                    {
                        for (int i = 0; i < git.GenericArguments.Count; i++)
                        {
                            var ga = git.GenericArguments[i];
                            if (ga == typeRef)
                            {
                                specialProcess = true;
                                if (spIdx == null)
                                {
                                    spIdx = new List <int>();
                                }
                                spIdx.Add(i);
                            }
                        }
                    }
                }
                if (specialProcess)
                {
                    //如果泛型参数是自身,则必须要特殊处理,否则会StackOverflow
                    var elementType = appdomain.GetType(((GenericInstanceType)definition.BaseType).ElementType, this, null);
                    foreach (var i in appdomain.CrossBindingAdaptors)
                    {
                        if (i.Key.IsGenericType && !i.Key.IsGenericTypeDefinition)
                        {
                            var gd = i.Key.GetGenericTypeDefinition();
                            if (gd == elementType.TypeForCLR)
                            {
                                var  ga    = i.Key.GetGenericArguments();
                                bool match = true;
                                foreach (var j in spIdx)
                                {
                                    if (ga[j] != i.Value.AdaptorType)
                                    {
                                        match = false;
                                        break;
                                    }
                                }
                                if (match)
                                {
                                    baseType = i.Value;
                                    break;
                                }
                            }
                        }
                    }
                    if (baseType == null)
                    {
                        throw new TypeLoadException("Cannot find Adaptor for:" + definition.BaseType.FullName);
                    }
                }
                else
                {
                    baseType = appdomain.GetType(definition.BaseType, this, null);
                    if (baseType is CLRType)
                    {
                        if (baseType.TypeForCLR == typeof(Enum) || baseType.TypeForCLR == typeof(object) || baseType.TypeForCLR == typeof(ValueType) || baseType.TypeForCLR == typeof(System.Enum))
                        {//都是这样,无所谓
                            baseType = null;
                        }
                        else if (baseType.TypeForCLR == typeof(MulticastDelegate))
                        {
                            baseType   = null;
                            isDelegate = true;
                        }
                        else
                        {
                            CrossBindingAdaptor adaptor;
                            if (appdomain.CrossBindingAdaptors.TryGetValue(baseType.TypeForCLR, out adaptor))
                            {
                                baseType = adaptor;
                            }
                            else
                            {
                                throw new TypeLoadException("Cannot find Adaptor for:" + baseType.TypeForCLR.ToString());
                            }
                            //继承了其他系统类型
                            //env.logger.Log_Error("ScriptType:" + Name + " Based On a SystemType:" + BaseType.Name);
                            //HasSysBase = true;
                            //throw new Exception("不得继承系统类型,脚本类型系统和脚本类型系统是隔离的");
                        }
                    }
                }
            }
            var curBase = baseType;

            while (curBase is ILType)
            {
                curBase = curBase.BaseType;
            }
            firstCLRBaseType    = curBase;
            baseTypeInitialized = true;
        }
コード例 #19
0
 protected override void DisposeCore()
 {
     retType = null;
 }
コード例 #20
0
        /// <summary>
        /// Replace generic parameters with actual arguments
        /// </summary>
        private MonoTypeContext ResolveGenericParameter()
        {
            switch (Type.etype)
            {
            case ElementType.Var:
            case ElementType.MVar:
            {
                GenericParameter parameter    = (GenericParameter)Type;
                TypeReference    resolvedType = Arguments[parameter];
                return(new MonoTypeContext(resolvedType));
            }

            case ElementType.Array:
            {
                ArrayType       array           = (ArrayType)Type;
                MonoTypeContext arrayContext    = new MonoTypeContext(array.ElementType, Arguments);
                MonoTypeContext resolvedContext = arrayContext.ResolveGenericParameter();
                ArrayType       newArray        = new ArrayType(resolvedContext.Type, array.Rank);
                if (array.Rank > 1)
                {
                    for (int i = 0; i < array.Rank; i++)
                    {
                        newArray.Dimensions[i] = array.Dimensions[i];
                    }
                }
                return(new MonoTypeContext(newArray, Arguments));
            }

            case ElementType.GenericInst:
            {
                GenericInstanceType genericInstance = (GenericInstanceType)Type;
                GenericInstanceType newInstance     = new GenericInstanceType(genericInstance.ElementType);
                foreach (TypeReference argument in genericInstance.GenericArguments)
                {
                    MonoTypeContext argumentContext  = new MonoTypeContext(argument, Arguments);
                    MonoTypeContext resolvedArgument = argumentContext.Resolve();
                    newInstance.GenericArguments.Add(resolvedArgument.Type);
                }
                return(new MonoTypeContext(newInstance, Arguments));
            }

            case ElementType.ByRef:
            {
                ByReferenceType reference       = (ByReferenceType)Type;
                MonoTypeContext refContext      = new MonoTypeContext(reference.ElementType, Arguments);
                MonoTypeContext resolvedContext = refContext.ResolveGenericParameter();
                ByReferenceType newReference    = new ByReferenceType(resolvedContext.Type);
                return(new MonoTypeContext(newReference, Arguments));
            }

            case ElementType.Ptr:
            {
                PointerType     pointer         = (PointerType)Type;
                MonoTypeContext ptrContext      = new MonoTypeContext(pointer.ElementType, Arguments);
                MonoTypeContext resolvedContext = ptrContext.ResolveGenericParameter();
                PointerType     newPointer      = new PointerType(resolvedContext.Type);
                return(new MonoTypeContext(newPointer, Arguments));
            }

            case ElementType.Pinned:
            {
                PinnedType      pinned          = (PinnedType)Type;
                MonoTypeContext pinContext      = new MonoTypeContext(pinned.ElementType, Arguments);
                MonoTypeContext resolvedContext = pinContext.ResolveGenericParameter();
                PinnedType      newPinned       = new PinnedType(resolvedContext.Type);
                return(new MonoTypeContext(newPinned, Arguments));
            }

            case ElementType.FnPtr:
            {
                FunctionPointerType funcPtr    = (FunctionPointerType)Type;
                FunctionPointerType newFuncPtr = new FunctionPointerType();
                newFuncPtr.HasThis           = funcPtr.HasThis;
                newFuncPtr.ExplicitThis      = funcPtr.ExplicitThis;
                newFuncPtr.CallingConvention = funcPtr.CallingConvention;
                MonoTypeContext returnContext  = new MonoTypeContext(funcPtr.ReturnType, Arguments);
                MonoTypeContext resolvedReturn = returnContext.Resolve();
                newFuncPtr.ReturnType = resolvedReturn.Type;
                foreach (ParameterDefinition param in funcPtr.Parameters)
                {
                    MonoTypeContext     paramContext  = new MonoTypeContext(param.ParameterType, Arguments);
                    MonoTypeContext     resolvedParam = paramContext.Resolve();
                    ParameterDefinition newParameter  = new ParameterDefinition(param.Name, param.Attributes, resolvedParam.Type);
                    newFuncPtr.Parameters.Add(newParameter);
                }
                return(new MonoTypeContext(newFuncPtr, Arguments));
            }

            default:
                throw new Exception($"Unknown generic parameter container {Type}");
            }
        }
コード例 #21
0
        /// <exception cref="GenerateWriterException">Throws when writer could not be generated for type</exception>
        static MethodReference GenerateWriter(TypeReference variableReference)
        {
            if (variableReference.IsByReference)
            {
                throw new GenerateWriterException($"Cannot pass {variableReference.Name} by reference", variableReference);
            }

            // Arrays are special, if we resolve them, we get the element type,
            // eg int[] resolves to int
            // therefore process this before checks below
            if (variableReference.IsArray)
            {
                if (variableReference.IsMultidimensionalArray())
                {
                    throw new GenerateWriterException($"{variableReference.Name} is an unsupported type. Multidimensional arrays are not supported", variableReference);
                }
                TypeReference elementType = variableReference.GetElementType();
                return(GenerateGenericWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteArray)));
            }

            if (variableReference.Resolve()?.IsEnum ?? false)
            {
                // serialize enum as their base type
                return(GenerateEnumWriteFunc(variableReference));
            }

            // check for collections or nullable
            if (variableReference.Is(typeof(Nullable <>)))
            {
                GenericInstanceType genericInstance = (GenericInstanceType)variableReference;
                TypeReference       elementType     = genericInstance.GenericArguments[0];

                return(GenerateGenericWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteNullable)));
            }
            if (variableReference.Is(typeof(ArraySegment <>)))
            {
                GenericInstanceType genericInstance = (GenericInstanceType)variableReference;
                TypeReference       elementType     = genericInstance.GenericArguments[0];

                return(GenerateGenericWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteArraySegment)));
            }
            if (variableReference.Is(typeof(List <>)))
            {
                GenericInstanceType genericInstance = (GenericInstanceType)variableReference;
                TypeReference       elementType     = genericInstance.GenericArguments[0];

                return(GenerateGenericWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteList)));
            }

            if (variableReference.IsDerivedFrom <NetworkBehaviour>())
            {
                return(GetNetworkBehaviourWriter(variableReference));
            }

            // check for invalid types
            TypeDefinition variableDefinition = variableReference.Resolve();

            if (variableDefinition == null)
            {
                throw new GenerateWriterException($"{variableReference.Name} is not a supported type. Use a supported type or provide a custom writer", variableReference);
            }
            if (variableDefinition.IsDerivedFrom <UnityEngine.Component>())
            {
                throw new GenerateWriterException($"Cannot generate writer for component type {variableReference.Name}. Use a supported type or provide a custom writer", variableReference);
            }
            if (variableReference.Is <UnityEngine.Object>())
            {
                throw new GenerateWriterException($"Cannot generate writer for {variableReference.Name}. Use a supported type or provide a custom writer", variableReference);
            }
            if (variableReference.Is <UnityEngine.ScriptableObject>())
            {
                throw new GenerateWriterException($"Cannot generate writer for {variableReference.Name}. Use a supported type or provide a custom writer", variableReference);
            }
            if (variableDefinition.HasGenericParameters)
            {
                throw new GenerateWriterException($"Cannot generate writer for generic type {variableReference.Name}. Use a supported type or provide a custom writer", variableReference);
            }
            if (variableDefinition.IsInterface)
            {
                throw new GenerateWriterException($"Cannot generate writer for interface {variableReference.Name}. Use a supported type or provide a custom writer", variableReference);
            }
            if (variableDefinition.IsAbstract)
            {
                throw new GenerateWriterException($"Cannot generate writer for abstract class {variableReference.Name}. Use a supported type or provide a custom writer", variableReference);
            }

            // generate writer for class/struct
            return(GenerateClassOrStructWriterFunction(variableReference));
        }
コード例 #22
0
        private static GenericInstanceType MakeGenericType(GenericInstanceType genericInstanceProvider, GenericInstanceType type)
        {
            var result = new GenericInstanceType(type.ElementType);

            for (var i = 0; i < type.GenericArguments.Count; ++i)
            {
                result.GenericArguments.Add(InflateGenericType(genericInstanceProvider, type.GenericArguments [i]));
            }

            return(result);
        }
コード例 #23
0
        public TypeReference Resolve(TypeReference typeReference, bool resolveGenericParameters)
        {
            if (IsDummy())
            {
                return(typeReference);
            }

            if (m_TypeDefinitionContext != null && m_TypeDefinitionContext.GenericArguments.Contains(typeReference))
            {
                return(typeReference);
            }
            if (m_MethodDefinitionContext != null && m_MethodDefinitionContext.GenericArguments.Contains(typeReference))
            {
                return(typeReference);
            }

            switch (typeReference)
            {
            case GenericParameter genericParameter when m_TypeDefinitionContext != null && m_TypeDefinitionContext.GenericArguments.Contains(genericParameter):
                return(genericParameter);

            case GenericParameter genericParameter when m_MethodDefinitionContext != null && m_MethodDefinitionContext.GenericArguments.Contains(genericParameter):
                return(genericParameter);

            case GenericParameter genericParameter:
                return(ResolveGenericParameter(genericParameter));

            case ArrayType arrayType:
                return(new ArrayType(Resolve(arrayType.ElementType), arrayType.Rank));

            case PointerType pointerType:
                return(new PointerType(Resolve(pointerType.ElementType)));

            case ByReferenceType byReferenceType:
                return(new ByReferenceType(Resolve(byReferenceType.ElementType)));

            case PinnedType pinnedType:
                return(new PinnedType(Resolve(pinnedType.ElementType)));

            case GenericInstanceType genericInstanceType:
            {
                var newGenericInstanceType = new GenericInstanceType(genericInstanceType.ElementType);
                foreach (var genericArgument in genericInstanceType.GenericArguments)
                {
                    newGenericInstanceType.GenericArguments.Add(Resolve(genericArgument));
                }
                newGenericInstanceType.MetadataToken = genericInstanceType.MetadataToken;
                return(newGenericInstanceType);
            }

            case RequiredModifierType requiredModType:
                return(new RequiredModifierType(requiredModType.ModifierType, Resolve(requiredModType.ElementType, resolveGenericParameters)));

            case OptionalModifierType optionalModType:
                return(Resolve(optionalModType.ElementType, resolveGenericParameters));
            }

            if (resolveGenericParameters)
            {
                if (typeReference is TypeDefinition typeDefinition && typeDefinition.HasGenericParameters)
                {
                    var newGenericInstanceType = new GenericInstanceType(typeDefinition);
                    foreach (var gp in typeDefinition.GenericParameters)
                    {
                        newGenericInstanceType.GenericArguments.Add(Resolve(gp));
                    }
                    return(newGenericInstanceType);
                }
            }

            if (typeReference is TypeSpecification)
            {
                throw new NotSupportedException($"The type {typeReference.FullName} cannot be resolved correctly.");
            }

            return(typeReference);
        }
コード例 #24
0
        public static TypeReference InflateGenericType(GenericInstanceType genericInstanceProvider, TypeReference typeToInflate)
        {
            var arrayType = typeToInflate as ArrayType;

            if (arrayType != null)
            {
                var inflatedElementType = InflateGenericType(genericInstanceProvider, arrayType.ElementType);

                if (inflatedElementType != arrayType.ElementType)
                {
                    return(new ArrayType(inflatedElementType, arrayType.Rank));
                }

                return(arrayType);
            }

            var genericInst = typeToInflate as GenericInstanceType;

            if (genericInst != null)
            {
                return(MakeGenericType(genericInstanceProvider, genericInst));
            }

            var genericParameter = typeToInflate as GenericParameter;

            if (genericParameter != null)
            {
                if (genericParameter.Owner is MethodReference)
                {
                    return(genericParameter);
                }

                var elementType = genericInstanceProvider.ElementType.Resolve();
                var parameter   = elementType.GenericParameters.Single(p => p == genericParameter);
                return(genericInstanceProvider.GenericArguments [parameter.Position]);
            }

            var functionPointerType = typeToInflate as FunctionPointerType;

            if (functionPointerType != null)
            {
                var result = new FunctionPointerType();
                result.ReturnType = InflateGenericType(genericInstanceProvider, functionPointerType.ReturnType);

                for (int i = 0; i < functionPointerType.Parameters.Count; i++)
                {
                    var inflatedParameterType = InflateGenericType(genericInstanceProvider, functionPointerType.Parameters [i].ParameterType);
                    result.Parameters.Add(new ParameterDefinition(inflatedParameterType));
                }

                return(result);
            }

            var modifierType = typeToInflate as IModifierType;

            if (modifierType != null)
            {
                var modifier    = InflateGenericType(genericInstanceProvider, modifierType.ModifierType);
                var elementType = InflateGenericType(genericInstanceProvider, modifierType.ElementType);

                if (modifierType is OptionalModifierType)
                {
                    return(new OptionalModifierType(modifier, elementType));
                }

                return(new RequiredModifierType(modifier, elementType));
            }

            var pinnedType = typeToInflate as PinnedType;

            if (pinnedType != null)
            {
                var elementType = InflateGenericType(genericInstanceProvider, pinnedType.ElementType);

                if (elementType != pinnedType.ElementType)
                {
                    return(new PinnedType(elementType));
                }

                return(pinnedType);
            }

            var pointerType = typeToInflate as PointerType;

            if (pointerType != null)
            {
                var elementType = InflateGenericType(genericInstanceProvider, pointerType.ElementType);

                if (elementType != pointerType.ElementType)
                {
                    return(new PointerType(elementType));
                }

                return(pointerType);
            }

            var byReferenceType = typeToInflate as ByReferenceType;

            if (byReferenceType != null)
            {
                var elementType = InflateGenericType(genericInstanceProvider, byReferenceType.ElementType);

                if (elementType != byReferenceType.ElementType)
                {
                    return(new ByReferenceType(elementType));
                }

                return(byReferenceType);
            }

            var sentinelType = typeToInflate as SentinelType;

            if (sentinelType != null)
            {
                var elementType = InflateGenericType(genericInstanceProvider, sentinelType.ElementType);

                if (elementType != sentinelType.ElementType)
                {
                    return(new SentinelType(elementType));
                }

                return(sentinelType);
            }

            return(typeToInflate);
        }
コード例 #25
0
        static GenericInstanceType ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericInstanceType genericInstanceType1)
        {
            if (!genericInstanceType1.ContainsGenericParameters())
            {
                return(genericInstanceType1);
            }

            var newGenericInstance = new GenericInstanceType(genericInstanceType1.ElementType);

            foreach (var genericArgument in genericInstanceType1.GenericArguments)
            {
                if (!genericArgument.IsGenericParameter)
                {
                    newGenericInstance.GenericArguments.Add(ResolveIfNeeded(genericInstanceMethod, genericInstanceType, genericArgument));
                    continue;
                }

                var genParam = (GenericParameter)genericArgument;

                switch (genParam.Type)
                {
                case GenericParameterType.Type:
                {
                    if (genericInstanceType == null)
                    {
                        throw new NotSupportedException();
                    }

                    newGenericInstance.GenericArguments.Add(genericInstanceType.GenericArguments[genParam.Position]);
                }
                break;

                case GenericParameterType.Method:
                {
                    if (genericInstanceMethod == null)
                    {
                        newGenericInstance.GenericArguments.Add(genParam);
                    }
                    else
                    {
                        newGenericInstance.GenericArguments.Add(genericInstanceMethod.GenericArguments[genParam.Position]);
                    }
                }
                break;
                }
            }

            return(newGenericInstance);
        }
コード例 #26
0
        public TypeReference ImportReference(Type type, IGenericParameterProvider context)
        {
            if (CachedTypes.TryGetValue(type, out TypeReference typeRef))
            {
                return(typeRef);
            }

            if (UseDefault)
            {
                return(CachedTypes[type] = Default.ImportReference(type, context));
            }

            if (type.HasElementType)
            {
                if (type.IsByRef)
                {
                    return(CachedTypes[type] = new ByReferenceType(ImportReference(type.GetElementType(), context)));
                }

                if (type.IsPointer)
                {
                    return(CachedTypes[type] = new PointerType(ImportReference(type.GetElementType(), context)));
                }

                if (type.IsArray)
                {
                    ArrayType at = new ArrayType(ImportReference(type.GetElementType(), context), type.GetArrayRank());
                    if (type != type.GetElementType().MakeArrayType())
                    {
                        // Non-SzArray
                        // TODO: Find a way to get the bounds without instantiating the array type!

                        /*
                         * Array a = Array.CreateInstance(type, new int[type.GetArrayRank()]);
                         * if (
                         *  at.Rank > 1
                         *  && a.IsFixedSize
                         * ) {
                         *  for (int i = 0; i < at.Rank; i++)
                         *      at.Dimensions[i] = new ArrayDimension(a.GetLowerBound(i), a.GetUpperBound(i));
                         * }
                         */
                        // For now, always assume [0...,0...,
                        // Array.CreateInstance only accepts lower bounds anyway.
                        for (int i = 0; i < at.Rank; i++)
                        {
                            at.Dimensions[i] = new ArrayDimension(0, null);
                        }
                    }
                    return(CachedTypes[type] = at);
                }
            }

            bool isGeneric = type.IsGenericType;

            if (isGeneric && !type.IsGenericTypeDefinition)
            {
                GenericInstanceType git = new GenericInstanceType(ImportReference(type.GetGenericTypeDefinition(), context));
                foreach (Type arg in type.GetGenericArguments())
                {
                    git.GenericArguments.Add(ImportReference(arg, context));
                }
                return(git);
            }

            if (type.IsGenericParameter)
            {
                return(CachedTypes[type] = ImportGenericParameter(type, context));
            }

            if (ElementTypes.TryGetValue(type, out typeRef))
            {
                return(CachedTypes[type] = typeRef);
            }

            typeRef = new TypeReference(
                string.Empty,
                type.Name,
                Module,
                ImportReference(type.Assembly.GetName()),
                type.IsValueType
                );

            if (type.IsNested)
            {
                typeRef.DeclaringType = ImportReference(type.DeclaringType, context);
            }
            else if (type.Namespace != null)
            {
                typeRef.Namespace = type.Namespace;
            }

            if (type.IsGenericType)
            {
                foreach (Type param in type.GetGenericArguments())
                {
                    typeRef.GenericParameters.Add(new GenericParameter(param.Name, typeRef));
                }
            }

            return(CachedTypes[type] = typeRef);
        }
コード例 #27
0
        /// <summary>
        /// Executes this instance.
        /// </summary>
        /// <exception cref="Exception">
        /// reactiveObjectExtensions is null
        /// or
        /// raisePropertyChangedMethod is null
        /// or
        /// reactiveDecoratorAttribute is null.
        /// </exception>
        public void Execute()
        {
            var reactiveUI = ModuleDefinition?.AssemblyReferences.Where(x => x.Name == "ReactiveUI").OrderByDescending(x => x.Version).FirstOrDefault();

            if (reactiveUI == null)
            {
                LogInfo?.Invoke("Could not find assembly: ReactiveUI (" + string.Join(", ", ModuleDefinition?.AssemblyReferences.Select(x => x.Name)) + ")");
                return;
            }

            LogInfo?.Invoke($"{reactiveUI.Name} {reactiveUI.Version}");
            var helpers = ModuleDefinition?.AssemblyReferences.Where(x => x.Name == "ReactiveUI.Fody.Helpers").OrderByDescending(x => x.Version).FirstOrDefault();

            if (helpers == null)
            {
                LogInfo?.Invoke("Could not find assembly: ReactiveUI.Fody.Helpers (" + string.Join(", ", ModuleDefinition?.AssemblyReferences.Select(x => x.Name)) + ")");
                return;
            }

            LogInfo?.Invoke($"{helpers.Name} {helpers.Version}");
            var reactiveObject = new TypeReference("ReactiveUI", "IReactiveObject", ModuleDefinition, reactiveUI);

            var targetTypes = ModuleDefinition.GetAllTypes().Where(x => x.BaseType != null && reactiveObject.IsAssignableFrom(x.BaseType)).ToArray();
            var reactiveObjectExtensions = new TypeReference("ReactiveUI", "IReactiveObjectExtensions", ModuleDefinition, reactiveUI).Resolve();

            if (reactiveObjectExtensions == null)
            {
                throw new Exception("reactiveObjectExtensions is null");
            }

            var raisePropertyChangedMethod = ModuleDefinition?.ImportReference(reactiveObjectExtensions.Methods.Single(x => x.Name == "RaisePropertyChanged"));

            if (raisePropertyChangedMethod == null)
            {
                throw new Exception("raisePropertyChangedMethod is null");
            }

            var reactiveDependencyAttribute = ModuleDefinition?.FindType("ReactiveUI.Fody.Helpers", "ReactiveDependencyAttribute", helpers);

            if (reactiveDependencyAttribute == null)
            {
                throw new Exception("reactiveDecoratorAttribute is null");
            }

            foreach (var targetType in targetTypes.Where(x => x.Properties.Any(y => y.IsDefined(reactiveDependencyAttribute))).ToArray())
            {
                foreach (var facadeProperty in targetType.Properties.Where(x => x.IsDefined(reactiveDependencyAttribute)).ToArray())
                {
                    // If the property already has a body then do not weave to prevent loss of instructions
                    if (!facadeProperty.GetMethod.Body.Instructions.Any(x => x.Operand is FieldReference) || facadeProperty.GetMethod.Body.HasVariables)
                    {
                        LogError?.Invoke($"Property {facadeProperty.Name} is not an auto property and therefore not suitable for ReactiveDependency weaving");
                        continue;
                    }

                    var attribute = facadeProperty.CustomAttributes.First(x => x.AttributeType.FullName == reactiveDependencyAttribute.FullName);

                    var targetNamedArgument = attribute.ConstructorArguments.FirstOrDefault();
                    var targetValue         = targetNamedArgument.Value?.ToString();
                    if (string.IsNullOrEmpty(targetValue))
                    {
                        LogError?.Invoke("No target property defined on the object");
                        continue;
                    }

                    if (targetType.Properties.All(x => x.Name != targetValue) && targetType.Fields.All(x => x.Name != targetValue))
                    {
                        LogError?.Invoke($"dependency object property/field name '{targetValue}' not found on target type {targetType.Name}");
                        continue;
                    }

                    var objPropertyTarget = targetType.Properties.FirstOrDefault(x => x.Name == targetValue);
                    var objFieldTarget    = targetType.Fields.FirstOrDefault(x => x.Name == targetValue);

                    var objDependencyTargetType = objPropertyTarget != null
                        ? objPropertyTarget.PropertyType.Resolve()
                        : objFieldTarget?.FieldType.Resolve();

                    if (objDependencyTargetType == null)
                    {
                        LogError?.Invoke("Couldn't result the dependency type");
                        continue;
                    }

                    // Look for the target property on the member obj
                    var destinationPropertyNamedArgument = attribute.Properties.FirstOrDefault(x => x.Name == "TargetProperty");
                    var destinationPropertyName          = destinationPropertyNamedArgument.Argument.Value?.ToString();

                    // If no target property was specified use this property's name as the target on the decorated object (ala a decorated property)
                    if (string.IsNullOrEmpty(destinationPropertyName))
                    {
                        destinationPropertyName = facadeProperty.Name;
                    }

                    if (objDependencyTargetType.Properties.All(x => x.Name != destinationPropertyName))
                    {
                        LogError?.Invoke($"Target property {destinationPropertyName} on dependency of type {objDependencyTargetType.DeclaringType.Name} not found");
                        continue;
                    }

                    var destinationProperty = objDependencyTargetType.Properties.First(x => x.Name == destinationPropertyName);

                    // The property on the facade/decorator should have a setter
                    if (facadeProperty.SetMethod == null)
                    {
                        LogError?.Invoke($"Property {facadeProperty.DeclaringType.FullName}.{facadeProperty.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [ReactiveDecorator]");
                        continue;
                    }

                    // The property on the dependency should have a setter e.g. Dependency.SomeProperty = value;
                    if (destinationProperty.SetMethod == null)
                    {
                        LogError?.Invoke($"Dependency object's property {destinationProperty.DeclaringType.FullName}.{destinationProperty.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [ReactiveDecorator]");
                        continue;
                    }

                    // Remove old field (the generated backing field for the auto property)
                    var oldField           = (FieldReference)facadeProperty.GetMethod.Body.Instructions.Single(x => x.Operand is FieldReference).Operand;
                    var oldFieldDefinition = oldField.Resolve();
                    targetType.Fields.Remove(oldFieldDefinition);

                    // See if there exists an initializer for the auto-property
                    var constructors = targetType.Methods.Where(x => x.IsConstructor);
                    foreach (var constructor in constructors)
                    {
                        var fieldAssignment = constructor.Body.Instructions.SingleOrDefault(x => Equals(x.Operand, oldFieldDefinition) || Equals(x.Operand, oldField));
                        if (fieldAssignment != null)
                        {
                            // Replace field assignment with a property set (the stack semantics are the same for both,
                            // so happily we don't have to manipulate the bytecode any further.)
                            var setterCall = constructor.Body.GetILProcessor().Create(facadeProperty.SetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, facadeProperty.SetMethod);
                            constructor.Body.GetILProcessor().Replace(fieldAssignment, setterCall);
                        }
                    }

                    // Build out the getter which simply returns the value of the generated field
                    facadeProperty.GetMethod.Body = new MethodBody(facadeProperty.GetMethod);
                    facadeProperty.GetMethod.Body.Emit(il =>
                    {
                        il.Emit(OpCodes.Ldarg_0);
                        if (objPropertyTarget != null)
                        {
                            il.Emit(objPropertyTarget.GetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, objPropertyTarget.GetMethod);
                        }
                        else
                        {
                            il.Emit(OpCodes.Ldfld, objFieldTarget);
                        }

                        il.Emit(destinationProperty.GetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, destinationProperty.GetMethod);
                        il.Emit(OpCodes.Ret);
                    });

                    TypeReference genericTargetType = targetType;
                    if (targetType.HasGenericParameters)
                    {
                        var genericDeclaration = new GenericInstanceType(targetType);
                        foreach (var parameter in targetType.GenericParameters)
                        {
                            genericDeclaration.GenericArguments.Add(parameter);
                        }

                        genericTargetType = genericDeclaration;
                    }

                    var methodReference = raisePropertyChangedMethod.MakeGenericMethod(genericTargetType);
                    facadeProperty.SetMethod.Body = new MethodBody(facadeProperty.SetMethod);
                    facadeProperty.SetMethod.Body.Emit(il =>
                    {
                        il.Emit(OpCodes.Ldarg_0);
                        if (objPropertyTarget != null)
                        {
                            il.Emit(objPropertyTarget.GetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, objPropertyTarget.GetMethod);
                        }
                        else
                        {
                            il.Emit(OpCodes.Ldfld, objFieldTarget);
                        }

                        il.Emit(OpCodes.Ldarg_1);
                        il.Emit(destinationProperty.SetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, destinationProperty.SetMethod); // Set the nested property
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(OpCodes.Ldstr, facadeProperty.Name);                                                                       // "PropertyName"
                        il.Emit(OpCodes.Call, methodReference);                                                                            // this.RaisePropertyChanged("PropertyName")
                        il.Emit(OpCodes.Ret);
                    });
                }
            }
        }
コード例 #28
0
 public static void GetEnumerator(this ILProcessor processor, GenericInstanceType @this)
 => processor.Call(@this.FindMethod(nameof(GetEnumerator), NoParameter));
コード例 #29
0
        private static TypeReference InflateGenericType(GenericInstanceType genericInstanceProvider, TypeReference typeToInflate)
        {
            ArrayType type = typeToInflate as ArrayType;

            if (type != null)
            {
                TypeReference reference = InflateGenericType(genericInstanceProvider, type.ElementType);
                if (reference != type.ElementType)
                {
                    return(new ArrayType(reference, type.Rank));
                }
                return(type);
            }
            GenericInstanceType baseType = typeToInflate as GenericInstanceType;

            if (baseType != null)
            {
                return(MakeGenericType(genericInstanceProvider, baseType));
            }
            GenericParameter genericParameter = typeToInflate as GenericParameter;

            if (genericParameter != null)
            {
                GenericParameter parameter = ResolveType(genericInstanceProvider.ElementType).GenericParameters.Single <GenericParameter>(p => p == genericParameter);
                return(genericInstanceProvider.GenericArguments[parameter.Position]);
            }
            FunctionPointerType type3 = typeToInflate as FunctionPointerType;

            if (type3 != null)
            {
                FunctionPointerType type9 = new FunctionPointerType {
                    ReturnType = InflateGenericType(genericInstanceProvider, type3.ReturnType)
                };
                for (int i = 0; i < type3.Parameters.Count; i++)
                {
                    TypeReference parameterType = InflateGenericType(genericInstanceProvider, type3.Parameters[i].ParameterType);
                    type9.Parameters.Add(new ParameterDefinition(parameterType));
                }
                return(type9);
            }
            IModifierType type4 = typeToInflate as IModifierType;

            if (type4 != null)
            {
                TypeReference modifierType = InflateGenericType(genericInstanceProvider, type4.ModifierType);
                TypeReference reference4   = InflateGenericType(genericInstanceProvider, type4.ElementType);
                if (type4 is OptionalModifierType)
                {
                    return(new OptionalModifierType(modifierType, reference4));
                }
                return(new RequiredModifierType(modifierType, reference4));
            }
            PinnedType type5 = typeToInflate as PinnedType;

            if (type5 != null)
            {
                TypeReference reference5 = InflateGenericType(genericInstanceProvider, type5.ElementType);
                if (reference5 != type5.ElementType)
                {
                    return(new PinnedType(reference5));
                }
                return(type5);
            }
            PointerType type6 = typeToInflate as PointerType;

            if (type6 != null)
            {
                TypeReference reference6 = InflateGenericType(genericInstanceProvider, type6.ElementType);
                if (reference6 != type6.ElementType)
                {
                    return(new PointerType(reference6));
                }
                return(type6);
            }
            ByReferenceType type7 = typeToInflate as ByReferenceType;

            if (type7 != null)
            {
                TypeReference reference7 = InflateGenericType(genericInstanceProvider, type7.ElementType);
                if (reference7 != type7.ElementType)
                {
                    return(new ByReferenceType(reference7));
                }
                return(type7);
            }
            SentinelType type8 = typeToInflate as SentinelType;

            if (type8 == null)
            {
                return(typeToInflate);
            }
            TypeReference reference8 = InflateGenericType(genericInstanceProvider, type8.ElementType);

            if (reference8 != type8.ElementType)
            {
                return(new SentinelType(reference8));
            }
            return(type8);
        }
コード例 #30
0
 private static string GetGenericInstanceName(GenericInstanceType genericInstance)
 {
     return(GetGenericName(genericInstance.ElementType, genericInstance.GenericArguments));
 }
コード例 #31
0
		private static MethodDefinition GetImplementedMethodFromGenericInstanceType(this MethodDefinition self, GenericInstanceType type)
		{
			TypeDefinition typeDef = type.Resolve();

			if (typeDef == null)
			{
				return null;
			}

			foreach (MethodDefinition method in typeDef.Methods)
			{
				if (method.Name == self.Name)
				{
					if (method.HasParameters && self.HasParameters && method.Parameters.Count == self.Parameters.Count)
					{
						if (method.ReturnType.IsGenericParameter)
						{
							int parameterPosition = (method.ReturnType as GenericParameter).Position;

							TypeReference genericArgument;
							if (!type.PostionToArgument.TryGetValue(parameterPosition, out genericArgument))
							{
								continue;
							}

							if (genericArgument.FullName != self.ReturnType.FullName)
							{
								continue;
							}
						}
						else if (method.ReturnType.FullName != self.ReturnType.FullName)
						{
							continue;
						}

						for (int i = 0; i < method.Parameters.Count; i++)
						{
							TypeReference parameterType = method.Parameters[i].ParameterType;

							if (parameterType.IsGenericParameter)
							{
								int parameterPosition = (parameterType as GenericParameter).Position;

								TypeReference genericArgument;
								if (!type.PostionToArgument.TryGetValue(parameterPosition, out genericArgument))
								{
									continue;
								}

								if (genericArgument.FullName != self.Parameters[i].ParameterType.FullName)
								{
									continue;
								}
							}
							else if (parameterType.FullName != self.Parameters[i].ParameterType.FullName)
							{
								continue;
							}
						}
					}

					return method;
				}
			}

			return null;
		}
コード例 #32
0
        /// <summary>
        /// Finds the serializer information.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="generic">If set to true, when using <see cref="DataSerializerGenericMode.Type"/>, it will returns the generic version instead of actual type one.</param>
        /// <returns></returns>
        /// <exception cref="System.InvalidOperationException">Not sure how to process this inherited serializer</exception>
        internal SerializableTypeInfo FindSerializerInfo(TypeReference type, bool generic)
        {
            if (type == null || type.FullName == typeof(object).FullName || type.FullName == typeof(ValueType).FullName || type.IsGenericParameter)
            {
                return(null);
            }

            var resolvedType = type.Resolve();

            // Nested type
            if (resolvedType.IsNested)
            {
                // Check public/private flags
                if (!resolvedType.IsNestedPublic && !resolvedType.IsNestedAssembly)
                {
                    return(null);
                }
            }

            if (resolvedType.IsEnum)
            {
                // Enum
                // Let's generate a EnumSerializer
                var enumSerializerType = SiliconStudioCoreAssembly.MainModule.GetTypeResolved("SiliconStudio.Core.Serialization.Serializers.EnumSerializer`1");
                var serializerType     = new GenericInstanceType(enumSerializerType);
                serializerType.GenericArguments.Add(type);

                var serializableTypeInfo = new SerializableTypeInfo(serializerType, true, DataSerializerGenericMode.None);
                AddSerializableType(type, serializableTypeInfo);
                return(serializableTypeInfo);
            }

            // 1. Check if there is a Serializable attribute
            // Note: Not anymore since we don't want all system types to have unknown complex serializers.
            //if (((resolvedType.Attributes & TypeAttributes.Serializable) == TypeAttributes.Serializable) || resolvedType.CustomAttributes.Any(x => x.AttributeType.FullName == typeof(SerializableAttribute).FullName))
            //{
            //    serializerInfo.Serializable = true;
            //    serializerInfo.ComplexSerializer = true;
            //    serializerInfo.ComplexSerializerName = SerializerTypeName(resolvedType);
            //    return serializerInfo;
            //}

            // 2.1. Check if there is DataSerializerAttribute on this type (if yes, it is serializable, but not a "complex type")
            var dataSerializerAttribute =
                resolvedType.CustomAttributes.FirstOrDefault(
                    x => x.AttributeType.FullName == "SiliconStudio.Core.Serialization.DataSerializerAttribute");

            if (dataSerializerAttribute != null)
            {
                var modeField = dataSerializerAttribute.Fields.FirstOrDefault(x => x.Name == "Mode");
                var mode      = (modeField.Name != null) ? (DataSerializerGenericMode)modeField.Argument.Value : DataSerializerGenericMode.None;

                // TODO: Replace with ResolveGenericsVisitor
                var dataSerializerType = ((TypeReference)dataSerializerAttribute.ConstructorArguments[0].Value);
                if (mode == DataSerializerGenericMode.Type || (mode == DataSerializerGenericMode.TypeAndGenericArguments && type is GenericInstanceType))
                {
                    var genericSerializableTypeInfo = new SerializableTypeInfo(dataSerializerType, true, mode)
                    {
                        Inherited = true
                    };
                    AddSerializableType(type, genericSerializableTypeInfo);

                    var actualSerializerType = new GenericInstanceType(dataSerializerType);

                    // Add Type as generic arguments
                    actualSerializerType.GenericArguments.Add(type);

                    // If necessary, add generic arguments too
                    if (mode == DataSerializerGenericMode.TypeAndGenericArguments)
                    {
                        foreach (var genericArgument in ((GenericInstanceType)type).GenericArguments)
                        {
                            actualSerializerType.GenericArguments.Add(genericArgument);
                        }
                    }

                    // Special case for GenericMode == DataSerializerGenericMode.Type: we store actual serializer instantiation in SerializerType (alongside the generic version in GenericSerializerType).
                    var serializableTypeInfo = new SerializableTypeInfo(actualSerializerType, true);
                    AddSerializableType(type, serializableTypeInfo);

                    if (!generic)
                    {
                        return(serializableTypeInfo);
                    }

                    return(genericSerializableTypeInfo);
                }
                else
                {
                    var serializableTypeInfo = new SerializableTypeInfo(dataSerializerType, true, mode)
                    {
                        Inherited = false
                    };
                    AddSerializableType(type, serializableTypeInfo);
                    return(serializableTypeInfo);
                }
            }

            // 2.2. Check if SerializableExtendedAttribute is set on this class, or any of its base class with ApplyHierarchy
            var serializableExtendedAttribute =
                resolvedType.CustomAttributes.FirstOrDefault(
                    x => x.AttributeType.FullName == "SiliconStudio.Core.DataContractAttribute");

            if (dataSerializerAttribute == null && serializableExtendedAttribute != null)
            {
                // CHeck if ApplyHierarchy is active, otherwise it needs to be the exact type.
                var inherited = serializableExtendedAttribute.Properties.Where(x => x.Name == "Inherited")
                                .Select(x => (bool)x.Argument.Value)
                                .FirstOrDefault();

                var serializableTypeInfo = CreateComplexSerializer(type);
                serializableTypeInfo.Inherited = inherited;

                // Process members
                ProcessComplexSerializerMembers(type, serializableTypeInfo);

                return(serializableTypeInfo);
            }

            // Check if parent type contains Inherited attribute
            var parentType = ResolveGenericsVisitor.Process(type, type.Resolve().BaseType);

            if (parentType != null)
            {
                // Generate serializer for parent type
                var parentSerializableInfoType = GenerateSerializer(parentType.Resolve(), false, generic: true);

                // If Inherited flag is on, we also generate a serializer for this type
                if (parentSerializableInfoType != null && parentSerializableInfoType.Inherited)
                {
                    if (parentSerializableInfoType.ComplexSerializer)
                    {
                        var serializableTypeInfo = CreateComplexSerializer(type);
                        serializableTypeInfo.Inherited = true;

                        // Process members
                        ProcessComplexSerializerMembers(type, serializableTypeInfo);

                        return(serializableTypeInfo);
                    }
                    else if (parentSerializableInfoType.Mode == DataSerializerGenericMode.Type || parentSerializableInfoType.Mode == DataSerializerGenericMode.TypeAndGenericArguments)
                    {
                        // Register generic version
                        var genericSerializableTypeInfo = new SerializableTypeInfo(parentSerializableInfoType.SerializerType, true, parentSerializableInfoType.Mode);
                        AddSerializableType(type, genericSerializableTypeInfo);

                        if (!type.HasGenericParameters)
                        {
                            var actualSerializerType = new GenericInstanceType(parentSerializableInfoType.SerializerType);

                            // Add Type as generic arguments
                            actualSerializerType.GenericArguments.Add(type);

                            // If necessary, add generic arguments too
                            if (parentSerializableInfoType.Mode == DataSerializerGenericMode.TypeAndGenericArguments)
                            {
                                foreach (var genericArgument in ((GenericInstanceType)parentType).GenericArguments)
                                {
                                    actualSerializerType.GenericArguments.Add(genericArgument);
                                }
                            }

                            // Register actual type
                            var serializableTypeInfo = new SerializableTypeInfo(actualSerializerType, true);
                            AddSerializableType(type, serializableTypeInfo);

                            if (!generic)
                            {
                                return(serializableTypeInfo);
                            }
                        }

                        return(genericSerializableTypeInfo);
                    }
                    else
                    {
                        throw new InvalidOperationException("Not sure how to process this inherited serializer");
                    }
                }
            }

            return(null);
        }
コード例 #33
0
        /// <summary>
        /// Ensure the following type can be serialized. If not, try to register appropriate serializer.
        /// This method can be recursive.
        /// </summary>
        /// <param name="type">The type.</param>
        public SerializableTypeInfo GenerateSerializer(TypeReference type, bool force = true, string profile = "Default", bool generic = false)
        {
            var serializableTypes = GetSerializableTypes(profile);

            // Already handled?
            SerializableTypeInfo serializableTypeInfo;

            if (serializableTypes.TryGetSerializableTypeInfo(type, generic, out serializableTypeInfo))
            {
                return(serializableTypeInfo);
            }

            // Try to get one without generic
            if (generic && serializableTypes.TryGetSerializableTypeInfo(type, false, out serializableTypeInfo))
            {
                return(serializableTypeInfo);
            }

            // TDOO: Array, List, Generic types, etc... (equivalent of previous serializer factories)
            var arrayType = type as ArrayType;

            if (arrayType != null)
            {
                // Only proceed if element type is serializable (and in Default profile, otherwise ElementType is enough)
                if (GenerateSerializer(arrayType.ElementType, force, profile) != null)
                {
                    if (profile == "Default")
                    {
                        var arraySerializerType = SiliconStudioCoreAssembly.MainModule.GetTypeResolved("SiliconStudio.Core.Serialization.Serializers.ArraySerializer`1");
                        var serializerType      = new GenericInstanceType(arraySerializerType);
                        serializerType.GenericArguments.Add(arrayType.ElementType);
                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true), profile);
                        return(serializableTypeInfo);
                    }
                    else
                    {
                        // Fallback to default
                        return(GenerateSerializer(type, force, "Default"));
                    }
                }

                return(null);
            }

            // Try to match with existing generic serializer (for List, Dictionary, etc...)
            var genericInstanceType = type as GenericInstanceType;

            if (genericInstanceType != null)
            {
                var elementType = genericInstanceType.ElementType;
                SerializableTypeInfo elementSerializableTypeInfo;
                if ((elementSerializableTypeInfo = GenerateSerializer(elementType, false, profile, true)) != null)
                {
                    switch (elementSerializableTypeInfo.Mode)
                    {
                    case DataSerializerGenericMode.Type:
                    {
                        var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                        serializerType.GenericArguments.Add(type);

                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true)
                            {
                                ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer
                            }, profile);
                        break;
                    }

                    case DataSerializerGenericMode.TypeAndGenericArguments:
                    {
                        var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                        serializerType.GenericArguments.Add(type);
                        foreach (var genericArgument in genericInstanceType.GenericArguments)
                        {
                            // Generate serializer for each generic argument
                            //GenerateSerializer(genericArgument);

                            serializerType.GenericArguments.Add(genericArgument);
                        }

                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true)
                            {
                                ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer
                            }, profile);
                        break;
                    }

                    case DataSerializerGenericMode.GenericArguments:
                    {
                        var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                        foreach (var genericArgument in genericInstanceType.GenericArguments)
                        {
                            // Generate serializer for each generic argument
                            //GenerateSerializer(genericArgument);

                            serializerType.GenericArguments.Add(genericArgument);
                        }

                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true)
                            {
                                ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer
                            }, profile);
                        break;
                    }

                    default:
                        throw new NotImplementedException();
                    }

                    if (elementSerializableTypeInfo.ComplexSerializer)
                    {
                        ProcessComplexSerializerMembers(type, serializableTypeInfo);
                    }
                    return(serializableTypeInfo);
                }
            }

            // Check complex type definitions
            if (profile == "Default" && (serializableTypeInfo = FindSerializerInfo(type, generic)) != null)
            {
                return(serializableTypeInfo);
            }

            // Fallback to default
            if (profile != "Default")
            {
                return(GenerateSerializer(type, force, "Default", generic));
            }

            // Part after that is only if a serializer is absolutely necessary. This is skipped when scanning normal assemblies type that might have nothing to do with serialization.
            if (!force)
            {
                return(null);
            }

            // Non instantiable type? (object, interfaces, abstract classes)
            // Serializer can be null since they will be inherited anyway (handled through MemberSerializer)
            var resolvedType = type.Resolve();

            if (resolvedType.IsAbstract || resolvedType.IsAbstract || resolvedType.FullName == typeof(object).FullName)
            {
                AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(null, true), profile);
                return(serializableTypeInfo);
            }

            return(null);
        }
コード例 #34
0
        static MethodDefinition GenerateArraySegmentWriteFunc(TypeReference variable, int recursionCount)
        {
            GenericInstanceType genericInstance  = (GenericInstanceType)variable;
            TypeReference       elementType      = genericInstance.GenericArguments[0];
            MethodReference     elementWriteFunc = GetWriteFunc(elementType, recursionCount + 1);

            if (elementWriteFunc == null)
            {
                return(null);
            }

            string functionName = "_WriteArraySegment_" + elementType.Name + "_";

            if (variable.DeclaringType != null)
            {
                functionName += variable.DeclaringType.Name;
            }
            else
            {
                functionName += "None";
            }

            // create new writer for this type
            MethodDefinition writerFunc = new MethodDefinition(functionName,
                                                               MethodAttributes.Public |
                                                               MethodAttributes.Static |
                                                               MethodAttributes.HideBySig,
                                                               Weaver.voidType);

            writerFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
            writerFunc.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, variable));

            writerFunc.Body.Variables.Add(new VariableDefinition(Weaver.int32Type));
            writerFunc.Body.Variables.Add(new VariableDefinition(Weaver.int32Type));
            writerFunc.Body.InitLocals = true;

            ILProcessor worker = writerFunc.Body.GetILProcessor();

            MethodReference countref = Weaver.ArraySegmentCountReference.MakeHostInstanceGeneric(genericInstance);

            // int length = value.Count;
            worker.Append(worker.Create(OpCodes.Ldarga_S, (byte)1));
            worker.Append(worker.Create(OpCodes.Call, countref));
            worker.Append(worker.Create(OpCodes.Stloc_0));


            // writer.WritePackedInt32(length);
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Call, GetWriteFunc(Weaver.int32Type)));

            // Loop through the ArraySegment<T> and call the writer for each element.
            // generates this:
            // for (int i=0; i< length; i++)
            // {
            //    writer.Write(value.Array[i + value.Offset]);
            // }
            worker.Append(worker.Create(OpCodes.Ldc_I4_0));
            worker.Append(worker.Create(OpCodes.Stloc_1));
            Instruction labelHead = worker.Create(OpCodes.Nop);

            worker.Append(worker.Create(OpCodes.Br, labelHead));

            // loop body
            Instruction labelBody = worker.Create(OpCodes.Nop);

            worker.Append(labelBody);

            // writer.Write(value.Array[i + value.Offset]);
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldarga_S, (byte)1));
            worker.Append(worker.Create(OpCodes.Call, Weaver.ArraySegmentArrayReference.MakeHostInstanceGeneric(genericInstance)));
            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Ldarga_S, (byte)1));
            worker.Append(worker.Create(OpCodes.Call, Weaver.ArraySegmentOffsetReference.MakeHostInstanceGeneric(genericInstance)));
            worker.Append(worker.Create(OpCodes.Add));
            worker.Append(worker.Create(OpCodes.Ldelema, elementType));
            worker.Append(worker.Create(OpCodes.Ldobj, elementType));
            worker.Append(worker.Create(OpCodes.Call, elementWriteFunc));


            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Ldc_I4_1));
            worker.Append(worker.Create(OpCodes.Add));
            worker.Append(worker.Create(OpCodes.Stloc_1));

            // end for loop
            worker.Append(labelHead);
            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Blt, labelBody));

            // return
            worker.Append(worker.Create(OpCodes.Ret));
            return(writerFunc);
        }