/// <summary> /// Convert MarshalAsAttribute data into CustomAttributeData form. Returns null if the core assembly cannot be loaded or if the necessary /// types aren't in the core assembly. /// </summary> public static CustomAttributeData?TryComputeMarshalAsCustomAttributeData(Func <MarshalAsAttribute> marshalAsAttributeComputer, MetadataLoadContext loader) { // Make sure all the necessary framework types exist in this MetadataLoadContext's core assembly. If one doesn't, skip. CoreTypes ct = loader.GetAllFoundCoreTypes(); if (ct[CoreType.String] == null || ct[CoreType.Boolean] == null || ct[CoreType.UnmanagedType] == null || ct[CoreType.VarEnum] == null || ct[CoreType.Type] == null || ct[CoreType.Int16] == null || ct[CoreType.Int32] == null) { return(null); } ConstructorInfo?ci = loader.TryGetMarshalAsCtor(); if (ci == null) { return(null); } Func <CustomAttributeArguments> argumentsPromise = () => { // The expensive work goes in here. It will not execute unless someone invokes the Constructor/NamedArguments properties on // the CustomAttributeData. MarshalAsAttribute ma = marshalAsAttributeComputer(); Type attributeType = ci.DeclaringType !; CustomAttributeTypedArgument[] cats = { new CustomAttributeTypedArgument(ct[CoreType.UnmanagedType] !, (int)(ma.Value)) };
/// <summary> /// Convert MarshalAsAttribute data into CustomAttributeData form. Returns null if the core assembly cannot be loaded or if the necessary /// types aren't in the core assembly. /// </summary> public static CustomAttributeData TryComputeMarshalAsCustomAttributeData(Func <MarshalAsAttribute> marshalAsAttributeComputer, MetadataLoadContext loader) { // Make sure all the necessary framework types exist in this MetadataLoadContext's core assembly. If one doesn't, skip. CoreTypes ct = loader.GetAllFoundCoreTypes(); if (ct[CoreType.String] == null || ct[CoreType.Boolean] == null || ct[CoreType.UnmanagedType] == null || ct[CoreType.VarEnum] == null || ct[CoreType.Type] == null || ct[CoreType.Int16] == null || ct[CoreType.Int32] == null) { return(null); } ConstructorInfo ci = loader.TryGetMarshalAsCtor(); if (ci == null) { return(null); } Func <CustomAttributeArguments> argumentsPromise = () => { // The expensive work goes in here. It will not execute unless someone invokes the Constructor/NamedArguments properties on // the CustomAttributeData. MarshalAsAttribute ma = marshalAsAttributeComputer(); Type attributeType = ci.DeclaringType; CustomAttributeTypedArgument[] cats = { new CustomAttributeTypedArgument(ct[CoreType.UnmanagedType], (int)(ma.Value)) }; List <CustomAttributeNamedArgument> cans = new List <CustomAttributeNamedArgument>(); cans.AddRange(new CustomAttributeNamedArgument[] { attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.ArraySubType), ct[CoreType.UnmanagedType], (int)ma.ArraySubType), attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.IidParameterIndex), ct[CoreType.Int32], ma.IidParameterIndex), attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.SafeArraySubType), ct[CoreType.VarEnum], (int)ma.SafeArraySubType), attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.SizeConst), ct[CoreType.Int32], ma.SizeConst), attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.SizeParamIndex), ct[CoreType.Int16], ma.SizeParamIndex), }); if (ma.SafeArrayUserDefinedSubType != null) { cans.Add(attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.SafeArrayUserDefinedSubType), ct[CoreType.Type], ma.SafeArrayUserDefinedSubType)); } if (ma.MarshalType != null) { cans.Add(attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.MarshalType), ct[CoreType.String], ma.MarshalType)); } if (ma.MarshalTypeRef != null) { cans.Add(attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.MarshalTypeRef), ct[CoreType.Type], ma.MarshalTypeRef)); } if (ma.MarshalCookie != null) { cans.Add(attributeType.ToCustomAttributeNamedArgument(nameof(MarshalAsAttribute.MarshalCookie), ct[CoreType.String], ma.MarshalCookie)); } return(new CustomAttributeArguments(cats, cans)); }; return(new RoPseudoCustomAttributeData(ci, argumentsPromise)); }