25using System.Collections.Generic;
26using System.Diagnostics;
27using System.Reflection.Metadata;
35 internal sealed class CustomAttributeBuilder
38 internal static readonly
ConstructorInfo LegacyPermissionSet =
new ConstructorBuilder(
null);
41 readonly
object[] constructorArgs;
43 readonly
object[] propertyValues;
45 readonly
object[] fieldValues;
64 private CustomAttributeBuilder(
ConstructorInfo con,
int securityAction,
byte[] blob)
68 this.constructorArgs =
new object[] { securityAction };
76 public CustomAttributeBuilder(
ConstructorInfo con,
object[] constructorArgs) :
77 this(con, constructorArgs, null, null, null, null)
89 public CustomAttributeBuilder(
ConstructorInfo con,
object[] constructorArgs,
FieldInfo[] namedFields,
object[] fieldValues) :
90 this(con, constructorArgs, null, null, namedFields, fieldValues)
102 public CustomAttributeBuilder(
ConstructorInfo con,
object[] constructorArgs,
PropertyInfo[] namedProperties,
object[] propertyValues) :
103 this(con, constructorArgs, namedProperties, propertyValues, null, null)
117 public CustomAttributeBuilder(
ConstructorInfo con,
object[] constructorArgs,
PropertyInfo[] namedProperties,
object[] propertyValues,
FieldInfo[] namedFields,
object[] fieldValues)
120 this.constructorArgs = constructorArgs;
121 this.namedProperties = namedProperties;
122 this.propertyValues = propertyValues;
123 this.namedFields = namedFields;
124 this.fieldValues = fieldValues;
127 public static CustomAttributeBuilder __FromBlob(
ConstructorInfo con,
byte[] blob)
129 return new CustomAttributeBuilder(con, blob);
132 public static CustomAttributeBuilder __FromBlob(
ConstructorInfo con,
int securityAction,
byte[] blob)
134 return new CustomAttributeBuilder(con, securityAction, blob);
137 public static CustomAttributeTypedArgument __MakeTypedArgument(
Type type,
object value)
139 return new CustomAttributeTypedArgument(type, value);
142 private sealed class BlobWriter
146 readonly CustomAttributeBuilder cab;
157 this.assembly = assembly;
162 internal void WriteCustomAttributeBlob()
167 var pi = cab.con.GetParameters();
168 for (
int i = 0; i < pi.Length; i++)
169 WriteFixedArg(pi[i].ParameterType, cab.constructorArgs[i]);
171 WriteNamedArguments(
false);
174 internal void WriteNamedArguments(
bool forDeclSecurity)
178 if (cab.namedFields !=
null)
180 named += cab.namedFields.Length;
182 if (cab.namedProperties !=
null)
184 named += cab.namedProperties.Length;
188 WritePackedLen(named);
192 WriteUInt16((ushort)named);
194 if (cab.namedFields !=
null)
196 for (
int i = 0; i < cab.namedFields.Length; i++)
198 WriteNamedArg(0x53, cab.namedFields[i].FieldType, cab.namedFields[i].Name, cab.fieldValues[i]);
201 if (cab.namedProperties !=
null)
203 for (
int i = 0; i < cab.namedProperties.Length; i++)
205 WriteNamedArg(0x54, cab.namedProperties[i].PropertyType, cab.namedProperties[i].Name, cab.propertyValues[i]);
210 void WriteNamedArg(
byte fieldOrProperty,
Type type,
string name,
object value)
212 WriteByte(fieldOrProperty);
213 WriteFieldOrPropType(type);
215 WriteFixedArg(type, value);
218 void WriteByte(
byte value)
223 void WriteUInt16(ushort value)
228 void WriteInt32(
int value)
233 void WriteFixedArg(
Type type,
object value)
235 var u = assembly.Universe;
236 if (type == u.System_String)
238 WriteString((
string)value);
240 else if (type == u.System_Boolean)
242 WriteByte((
bool)value ? (
byte)1 : (
byte)0);
244 else if (type == u.System_Char)
246 WriteUInt16((
char)value);
248 else if (type == u.System_SByte)
250 WriteByte((
byte)(sbyte)value);
252 else if (type == u.System_Byte)
254 WriteByte((
byte)value);
256 else if (type == u.System_Int16)
258 WriteUInt16((ushort)(
short)value);
260 else if (type == u.System_UInt16)
262 WriteUInt16((ushort)value);
264 else if (type == u.System_Int32)
266 WriteInt32((
int)value);
268 else if (type == u.System_UInt32)
270 WriteInt32((
int)(uint)value);
272 else if (type == u.System_Int64)
274 WriteInt64((
long)value);
276 else if (type == u.System_UInt64)
278 WriteInt64((
long)(ulong)value);
280 else if (type == u.System_Single)
282 WriteSingle((
float)value);
284 else if (type == u.System_Double)
286 WriteDouble((
double)value);
288 else if (type == u.System_Type)
290 WriteTypeName((
Type)value);
292 else if (type == u.System_Object)
296 type = u.System_String;
298 else if (value is
Type)
301 type = u.System_Type;
303 else if (value is CustomAttributeTypedArgument)
305 CustomAttributeTypedArgument cta = (CustomAttributeTypedArgument)value;
307 type = cta.ArgumentType;
311 type = u.Import(value.GetType());
313 WriteFieldOrPropType(type);
314 WriteFixedArg(type, value);
316 else if (type.IsArray)
324 Array array = (Array)value;
325 Type elemType = type.GetElementType();
326 WriteInt32(array.Length);
327 foreach (
object val
in array)
329 WriteFixedArg(elemType, val);
333 else if (type.IsEnum)
335 WriteFixedArg(type.GetEnumUnderlyingTypeImpl(), value);
339 throw new ArgumentException();
343 void WriteInt64(
long value)
348 void WriteSingle(
float value)
353 void WriteDouble(
double value)
358 void WriteTypeName(
Type type)
363 StringBuilder sb =
new StringBuilder();
364 GetTypeName(sb, type,
false);
365 name = sb.ToString();
370 void GetTypeName(StringBuilder sb,
Type type,
bool isTypeParam)
372 bool v1 = !assembly.ManifestModule.__IsMissing && assembly.ManifestModule.MDStreamVersion < 0x20000;
373 bool includeAssemblyName = type.Assembly != assembly && (!v1 || type.Assembly != type.Module.Universe.CoreLib);
374 if (isTypeParam && includeAssemblyName)
378 GetTypeNameImpl(sb, type);
379 if (includeAssemblyName)
391 sb.Append(type.Assembly.FullName.Replace(
"]",
"\\]")).Append(
']');
395 sb.Append(type.Assembly.FullName);
400 void GetTypeNameImpl(StringBuilder sb,
Type type)
402 if (type.HasElementType)
404 GetTypeNameImpl(sb, type.GetElementType());
407 else if (type.IsConstructedGenericType)
409 sb.Append(type.GetGenericTypeDefinition().FullName);
412 foreach (
Type typeParam
in type.GetGenericArguments())
415 GetTypeName(sb, typeParam,
true);
426 void WriteString(
string val)
431 void WritePackedLen(
int len)
433 bb.WriteCompressedUInt(len);
436 void WriteFieldOrPropType(
Type type)
438 var u = type.Module.Universe;
439 if (type == u.System_Type)
443 else if (type == u.System_Object)
447 else if (type == u.System_Boolean)
451 else if (type == u.System_Char)
455 else if (type == u.System_SByte)
459 else if (type == u.System_Byte)
463 else if (type == u.System_Int16)
467 else if (type == u.System_UInt16)
471 else if (type == u.System_Int32)
475 else if (type == u.System_UInt32)
479 else if (type == u.System_Int64)
483 else if (type == u.System_UInt64)
487 else if (type == u.System_Single)
491 else if (type == u.System_Double)
495 else if (type == u.System_String)
499 else if (type.IsArray)
502 WriteFieldOrPropType(type.GetElementType());
504 else if (type.IsEnum)
511 throw new ArgumentException();
521 internal BlobHandle WriteBlob(ModuleBuilder moduleBuilder)
531 var bw =
new BlobWriter(moduleBuilder.Assembly,
this, bb);
532 bw.WriteCustomAttributeBlob();
535 return moduleBuilder.GetOrAddBlob(bb.ToArray());
538 internal object GetConstructorArgument(
int pos)
540 return constructorArgs[pos];
543 internal int ConstructorArgumentCount
545 get {
return constructorArgs ==
null ? 0 : constructorArgs.Length; }
548 internal T? GetFieldValue<T>(
string name) where T :
struct
550 var val = GetFieldValue(name);
555 else if (val !=
null)
559 Debug.Assert(
Enum.GetUnderlyingType(typeof(T)) == val.GetType());
560 return (T)
Enum.ToObject(typeof(T), val);
564 Debug.Assert(
Enum.GetUnderlyingType(val.GetType()) == typeof(T));
565 return (T)Convert.ChangeType(val, typeof(T));
574 internal object GetFieldValue(
string name)
576 if (namedFields !=
null)
578 for (
int i = 0; i < namedFields.Length; i++)
580 if (namedFields[i].
Name == name)
582 return fieldValues[i];
589 internal bool IsLegacyDeclSecurity
593 return ReferenceEquals(con, LegacyPermissionSet)
594 || (con.DeclaringType == con.Module.Universe.System_Security_Permissions_PermissionSetAttribute
596 && (namedFields ==
null || namedFields.Length == 0)
597 && namedProperties !=
null
598 && namedProperties.Length == 1
599 && namedProperties[0].Name ==
"XML"
600 && propertyValues[0] is string);
604 internal BlobHandle WriteLegacyDeclSecurityBlob(ModuleBuilder moduleBuilder)
608 return moduleBuilder.GetOrAddBlob(blob);
612 return moduleBuilder.GetOrAddBlob(Encoding.Unicode.GetBytes((
string)propertyValues[0]));
616 internal void WriteNamedArgumentsForDeclSecurity(ModuleBuilder moduleBuilder,
ByteBuffer bb)
624 var bw =
new BlobWriter(moduleBuilder.Assembly,
this, bb);
625 bw.WriteNamedArguments(
true);
629 internal CustomAttributeData ToData(
Assembly asm)
633 if (constructorArgs !=
null)
634 return new CustomAttributeData(
asm, con, (
int)constructorArgs[0], blob, -1);
640 var namedArgs =
new List<CustomAttributeNamedArgument>();
642 if (namedProperties !=
null)
643 for (
int i = 0; i < namedProperties.Length; i++)
644 namedArgs.Add(
new CustomAttributeNamedArgument(namedProperties[i], RewrapValue(namedProperties[i].PropertyType, propertyValues[i])));
646 if (namedFields !=
null)
647 for (
int i = 0; i < namedFields.Length; i++)
648 namedArgs.Add(
new CustomAttributeNamedArgument(namedFields[i], RewrapValue(namedFields[i].FieldType, fieldValues[i])));
650 var args =
new List<CustomAttributeTypedArgument>(constructorArgs.Length);
651 var parameters = Constructor.GetParameters();
652 for (
int i = 0; i < constructorArgs.Length; i++)
653 args.Add(RewrapValue(parameters[i].ParameterType, constructorArgs[i]));
655 return new CustomAttributeData(
asm.ManifestModule, con, args, namedArgs);
659 static CustomAttributeTypedArgument RewrapValue(
Type type,
object value)
663 var array = (Array)value;
664 var arrayType = type.Module.Universe.Import(array.GetType());
665 return RewrapArray(arrayType, array);
667 else if (value is CustomAttributeTypedArgument)
669 var arg = (CustomAttributeTypedArgument)value;
670 if (arg.Value is Array)
671 return RewrapArray(arg.ArgumentType, (Array)arg.Value);
677 return new CustomAttributeTypedArgument(type, value);
681 static CustomAttributeTypedArgument RewrapArray(
Type arrayType, Array array)
683 var elementType = arrayType.GetElementType();
684 var newArray =
new CustomAttributeTypedArgument[array.Length];
685 for (
int i = 0; i < newArray.Length; i++)
686 newArray[i] = RewrapValue(elementType, array.GetValue(i));
688 return new CustomAttributeTypedArgument(arrayType, newArray);
691 internal bool HasBlob
693 get {
return blob !=
null; }
696 internal CustomAttributeBuilder DecodeBlob(
Assembly asm)
704 return ToData(
asm).__ToBuilder();
708 internal byte[] GetBlob(
Assembly asm)
711 var bw =
new BlobWriter(
asm,
this, bb);
712 bw.WriteCustomAttributeBlob();
716 internal KnownCA KnownCA
720 var attributeType = con.DeclaringType;
721 if (attributeType.IsConstructedGenericType)
722 return KnownCA.Unknown;
724 var typeName = attributeType.TypeName;
725 switch (typeName.Namespace)
728 switch (typeName.Name)
730 case "SerializableAttribute":
731 return KnownCA.SerializableAttribute;
732 case "NonSerializedAttribute":
733 return KnownCA.NonSerializedAttribute;
736 case "System.Runtime.CompilerServices":
737 switch (typeName.Name)
739 case "MethodImplAttribute":
740 return KnownCA.MethodImplAttribute;
741 case "SpecialNameAttribute":
742 return KnownCA.SpecialNameAttribute;
745 case "System.Runtime.InteropServices":
746 switch (typeName.Name)
748 case "DllImportAttribute":
749 return KnownCA.DllImportAttribute;
750 case "ComImportAttribute":
751 return KnownCA.ComImportAttribute;
752 case "MarshalAsAttribute":
753 return KnownCA.MarshalAsAttribute;
754 case "PreserveSigAttribute":
755 return KnownCA.PreserveSigAttribute;
757 return KnownCA.InAttribute;
759 return KnownCA.OutAttribute;
760 case "OptionalAttribute":
761 return KnownCA.OptionalAttribute;
762 case "StructLayoutAttribute":
763 return KnownCA.StructLayoutAttribute;
764 case "FieldOffsetAttribute":
765 return KnownCA.FieldOffsetAttribute;
770 if (typeName.Matches(
"System.Security.SuppressUnmanagedCodeSecurityAttribute"))
771 return KnownCA.SuppressUnmanagedCodeSecurityAttribute;
773 return KnownCA.Unknown;
IKVM.Reflection.Type Type
IKVM.Reflection.Assembly Assembly
IKVM.Reflection.ConstructorInfo ConstructorInfo
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.PropertyInfo PropertyInfo
global::java.lang.invoke.LambdaForm.Name Name