Пример #1
0
        private void DefineParameter(MethodBuilder methodBuilder, ConstructorBuilder constructorBuilder, Cci.IParameterDefinition paramDef)
        {
            // No explicit param row is needed if param has no flags (other than optionally IN),
            // no name and no references to the param row, such as CustomAttribute, Constant, or FieldMarshall
            var attributes = paramDef.GetAttributes(_context);
            var defaultValue = paramDef.GetDefaultValue(_context);

            if (defaultValue != null ||
                paramDef.IsOptional ||
                paramDef.IsOut ||
                paramDef.IsMarshalledExplicitly ||
                attributes.Any() ||
                paramDef.Name.Length > 0)
            {
                int index = paramDef is Cci.ReturnValueParameter ? 0 : paramDef.Index + 1;
                ParameterAttributes attrs = (ParameterAttributes)Cci.MetadataWriter.GetParameterFlags(paramDef);

                ParameterBuilder paramBuilder = (methodBuilder != null) ?
                    methodBuilder.DefineParameter(index, attrs, paramDef.Name) :
                    constructorBuilder.DefineParameter(index, attrs, paramDef.Name);

                if (defaultValue != null)
                {
                    object rawValue = defaultValue.Value;
                    if (rawValue == null)
                    {
                        var paramTypeRef = paramDef.GetType(_context);
                        if (paramTypeRef.IsValueType)
                        {
                            SetParameterDefaultStructValue(paramBuilder);
                        }
                        else
                        {
                            paramBuilder.SetConstant(null);
                        }
                    }
                    else
                    {
                        // TODO (tomat): Ref.Emit has too strict checks on the constant type. While it is ok to emit value,
                        // e.g. of type Int16 for parameter of type Int32 to metadata, Ref.Emit checks if these types are Type.IsAssignableFrom.
                        // To make this work we need to convert.
                        //
                        // We also need to support Nullable<T>.
                        if (rawValue.GetType().IsPrimitive)
                        {
                            // parameter type has already been resolved once when defining the method, so just retrive it:
                            Type paramType = ResolveType(paramDef.GetType(_context));

                            if (paramType.IsGenericType && paramType.GetGenericTypeDefinition() == typeof(Nullable<>))
                            {
                                paramType = paramType.GetGenericArguments()[0];
                            }

                            if (paramType.IsEnum)
                            {
                                // If emitting the enum, it isn't "created" as this stage so Enum.GetUnderlyingType() will throw
                                // Otherwise, if the enum is already defined, we should use Enum.GetUnderlyingType() to get the correct type
                                paramType = paramType is TypeBuilder ? paramType.UnderlyingSystemType : Enum.GetUnderlyingType(paramType);
                            }

                            rawValue = Convert.ChangeType(rawValue, paramType, System.Globalization.CultureInfo.InvariantCulture);
                        }

                        paramBuilder.SetConstant(rawValue);
                    }
                }

                if (paramDef.IsMarshalledExplicitly)
                {
                    // FieldMarshal
                    var marshallingInformation = paramDef.MarshallingInformation;

                    if (marshallingInformation != null)
                    {
                        paramBuilder.SetCustomAttribute(GetMarshalAsAttribute(marshallingInformation));
                    }
                    else
                    {
                        Debug.Assert(!paramDef.MarshallingDescriptor.IsDefaultOrEmpty);
                        // TODO:
                        throw new NotImplementedException();
                    }
                }

                EmitCustomAttributes(paramBuilder, attributes);
            }
        }
Пример #2
0
        private void FinishType(TypeBuilder typeBuilder, Cci.ITypeDefinition typeDef)
        {
            // implemented interfaces
            foreach (var iface in typeDef.Interfaces(_context))
            {
                // an implemented interface must be loaded before the type that implements it:
                typeBuilder.AddInterfaceImplementation(ResolveType(iface, dependentType: typeBuilder, valueTypeDependency: false));
            }

            // method implementations
            foreach (Cci.MethodImplementation impl in typeDef.GetExplicitImplementationOverrides(_context))
            {
                typeBuilder.DefineMethodOverride(ResolveMethod(impl.ImplementingMethod), ResolveMethod(impl.ImplementedMethod));
            }

            // properties (don't need to be defined prior custom attributes - we don't use CustomAttributeBuilders):
            foreach (Cci.IPropertyDefinition propertyDef in typeDef.GetProperties(_context))
            {
                EmitCustomAttributes(DefineProperty(typeBuilder, propertyDef), propertyDef.GetAttributes(_context));
            }

            // events
            foreach (Cci.IEventDefinition eventDef in typeDef.Events)
            {
                EmitCustomAttributes(DefineEvent(typeBuilder, eventDef), eventDef.GetAttributes(_context));
            }

            // custom attributes
            EmitCustomAttributes(typeBuilder, typeDef.GetAttributes(_context));

            // TODO:
            // decl security
        }