Exemplo n.º 1
0
        /// <summary>
        /// Create an argument for an annotation.
        /// 
        /// Java Annotations have some limitations compared to CLRs Attributes:
        ///    - While they can have default values, there is no way to 
        ///      specify an "unset" field or property.
        //     - 'null' is not allowed, neither as value nor as default (!)
        /// We have to emulate those two extra states to model
        /// the flexible constructor/property/field approach of
        /// CLR.
        /// We therefore save all values in arrays with the semantic:
        ///   - no elements   unset; this is the default value.
        ///   - one element:  the actual value
        ///   - two elements: null
        /// </summary>
        private static AnnotationArgument CreateAnnotationArgument(string name, TypeReference valueType, object value, DexTargetPackage targetPackage, XModule module)
        {
            if (valueType.IsSystemType())
            {
                // Convert .NET type reference to Dex type reference
                value = ((TypeReference) value).GetReference(targetPackage, module);
            }

            if (valueType.IsArray && value is CustomAttributeArgument[])
            {
                List<object> values = new List<object>();

                foreach (var argument in (CustomAttributeArgument[]) value)
                {
                    // dereference if argument is an object or params array.
                    var arg = argument.Value as CustomAttributeArgument? ?? argument;

                    object val;

                    if (arg.Type.IsSystemType())
                        val = ((TypeReference)arg.Value).GetReference(targetPackage, module);
                    else
                        val = arg.Value;

                    // Don't add an extra level of indirection for this 
                    // uncommon case until someone really needs it.
                    if (val == null)
                        throw new Exception("CustomAttributes: null values in array arguments are not supported.");

                    values.Add(val);
                }

                value = values.ToArray();
            }

            if (value != null)
            {
                // Note: there could be a special enum handling here, though it should work without.

                if (valueType.IsUInt64())
                    return new AnnotationArgument(name, new object[] { unchecked((long)(ulong)value) });
                if (valueType.IsUInt32())
                    return new AnnotationArgument(name, new object[] { unchecked((int)(uint)value) });
                if (!valueType.IsPrimitive || valueType.IsWide() || valueType.IsFloat())
                    return new AnnotationArgument(name, new[] { value });
                return new AnnotationArgument(name, new object[] { unchecked(Convert.ToInt32(value)) });
            }

            if(valueType.IsWide())
                return new AnnotationArgument(name, new object[] { 0L, 0L});
            if (valueType.IsPrimitive)
                return new AnnotationArgument(name, new object[] { 0, 0 });

            return new AnnotationArgument(name, new object[] { "", "" });
        }