コード例 #1
0
 /// <summary>
 /// Does the given type have any instance field that is a struct?
 /// </summary>
 private static bool HasInstanceStructFields(TypeDefinition type, out List <FieldDefinition> structFields)
 {
     structFields = null;
     if (type.IsEnum) // Class ctor is already created automatically for enums
     {
         return(false);
     }
     if (type.Name.StartsWith("<PrivateImplementationDetails>"))
     {
         return(false);
     }
     foreach (var field in type.Fields.Where(x => !x.IsStatic && x.IsReachable && StructFields.IsStructField(x)))
     {
         if (structFields == null)
         {
             structFields = new List <FieldDefinition>();
         }
         structFields.Add(field);
     }
     return(structFields != null);
 }
コード例 #2
0
            /// <summary>
            /// Create a CopyFrom method.
            /// </summary>
            private static MethodDefinition CreateCopyFromMethod(ReachableContext reachableContext, TypeDefinition type)
            {
                var typeSystem  = type.Module.TypeSystem;
                var method      = new MethodDefinition(NameConstants.Struct.CopyFromMethodName, MethodAttributes.Public, type);
                var sourceParam = new ParameterDefinition(type);

                method.Parameters.Add(sourceParam);
                method.DeclaringType = type;

                var body = new MethodBody(method);

                body.InitLocals = true;
                method.Body     = body;

                // Prepare code
                var seq = new ILSequence();

                seq.Emit(OpCodes.Nop);

                // Call base CopyFrom
                var baseType = (type.BaseType != null) ? type.BaseType.GetElementType().Resolve() : null;

                if ((baseType != null) && baseType.IsValueType && (baseType.FullName != "System.ValueType"))
                {
                    var baseMethod = new MethodReference(NameConstants.Struct.CopyFromMethodName, baseType, baseType)
                    {
                        HasThis = true
                    };
                    baseMethod.Parameters.Add(new ParameterDefinition(baseType));
                    seq.Emit(OpCodes.Ldarg, sourceParam);
                    seq.Emit(OpCodes.Call, baseMethod);
                }

                // Copy all fields
                foreach (var field in type.Fields.Where(x => !x.IsStatic))
                {
                    TypeDefinition fieldTypeDef;
                    var            isStructField = StructFields.IsStructField(field, out fieldTypeDef);

                    // Prepare for stfld
                    seq.Emit(OpCodes.Ldarg, body.ThisParameter);

                    // Load from source
                    seq.Emit(OpCodes.Ldarg, sourceParam);
                    seq.Emit(OpCodes.Ldfld, field);

                    // If struct, create clone
                    if (isStructField)
                    {
                        var cloneMethod = new MethodReference(NameConstants.Struct.CloneMethodName, fieldTypeDef, fieldTypeDef)
                        {
                            HasThis = true
                        };
                        seq.Emit(OpCodes.Call, cloneMethod);
                    }

                    // Save in this
                    seq.Emit(OpCodes.Stfld, field);
                }

                // Return this
                seq.Emit(OpCodes.Ldarg, body.ThisParameter);
                seq.Emit(OpCodes.Ret);

                // Append ret sequence
                seq.AppendTo(body);

                // Update offsets
                body.ComputeOffsets();

                // Add method
                type.Methods.Add(method);
                method.SetReachable(reachableContext);

                return(method);
            }