102 lines
5.1 KiB
C#
102 lines
5.1 KiB
C#
// Licensed to the .NET Foundation under one or more agreements.
|
|
// The .NET Foundation licenses this file to you under the MIT license.
|
|
// See the LICENSE file in the project root for more information.
|
|
// Original File: https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/libraries/Common/src/System/Reflection/Emit/IgnoreAccessChecksToAttributeBuilder.cs
|
|
using System.Linq;
|
|
|
|
namespace System.Reflection.Emit
|
|
{
|
|
internal static class IgnoreAccessChecksToAttributeBuilder
|
|
{
|
|
/// <summary>
|
|
/// Generate the declaration for the IgnoresAccessChecksToAttribute type.
|
|
/// This attribute will be both defined and used in the dynamic assembly.
|
|
/// Each usage identifies the name of the assembly containing non-public
|
|
/// types the dynamic assembly needs to access. Normally those types
|
|
/// would be inaccessible, but this attribute allows them to be visible.
|
|
/// It works like a reverse InternalsVisibleToAttribute.
|
|
/// This method returns the ConstructorInfo of the generated attribute.
|
|
/// </summary>
|
|
public static ConstructorInfo AddToModule(ModuleBuilder mb)
|
|
{
|
|
TypeBuilder attributeTypeBuilder =
|
|
mb.DefineType("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute",
|
|
TypeAttributes.Public | TypeAttributes.Class,
|
|
typeof(Attribute));
|
|
|
|
// Create backing field as:
|
|
// private string assemblyName;
|
|
FieldBuilder assemblyNameField =
|
|
attributeTypeBuilder.DefineField("assemblyName", typeof(string), FieldAttributes.Private);
|
|
|
|
// Create ctor as:
|
|
// public IgnoresAccessChecksToAttribute(string)
|
|
ConstructorBuilder constructorBuilder = attributeTypeBuilder.DefineConstructor(MethodAttributes.Public,
|
|
CallingConventions.HasThis,
|
|
new Type[] { assemblyNameField.FieldType });
|
|
|
|
ILGenerator il = constructorBuilder.GetILGenerator();
|
|
|
|
// Create ctor body as:
|
|
// this.assemblyName = {ctor parameter 0}
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
il.Emit(OpCodes.Ldarg, 1);
|
|
il.Emit(OpCodes.Stfld, assemblyNameField);
|
|
|
|
// return
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
// Define property as:
|
|
// public string AssemblyName {get { return this.assemblyName; } }
|
|
_ = attributeTypeBuilder.DefineProperty(
|
|
"AssemblyName",
|
|
PropertyAttributes.None,
|
|
CallingConventions.HasThis,
|
|
returnType: typeof(string),
|
|
parameterTypes: null);
|
|
|
|
MethodBuilder getterMethodBuilder = attributeTypeBuilder.DefineMethod(
|
|
"get_AssemblyName",
|
|
MethodAttributes.Public,
|
|
CallingConventions.HasThis,
|
|
returnType: typeof(string),
|
|
parameterTypes: null);
|
|
|
|
// Generate body:
|
|
// return this.assemblyName;
|
|
il = getterMethodBuilder.GetILGenerator();
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
il.Emit(OpCodes.Ldfld, assemblyNameField);
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
// Generate the AttributeUsage attribute for this attribute type:
|
|
// [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
|
TypeInfo attributeUsageTypeInfo = typeof(AttributeUsageAttribute).GetTypeInfo();
|
|
|
|
// Find the ctor that takes only AttributeTargets
|
|
ConstructorInfo attributeUsageConstructorInfo =
|
|
attributeUsageTypeInfo.DeclaredConstructors
|
|
.Single(c => c.GetParameters().Length == 1 &&
|
|
c.GetParameters()[0].ParameterType == typeof(AttributeTargets));
|
|
|
|
// Find the property to set AllowMultiple
|
|
PropertyInfo allowMultipleProperty =
|
|
attributeUsageTypeInfo.DeclaredProperties
|
|
.Single(f => string.Equals(f.Name, "AllowMultiple"));
|
|
|
|
// Create a builder to construct the instance via the ctor and property
|
|
CustomAttributeBuilder customAttributeBuilder =
|
|
new CustomAttributeBuilder(attributeUsageConstructorInfo,
|
|
new object[] { AttributeTargets.Assembly },
|
|
new PropertyInfo[] { allowMultipleProperty },
|
|
new object[] { true });
|
|
|
|
// Attach this attribute instance to the newly defined attribute type
|
|
attributeTypeBuilder.SetCustomAttribute(customAttributeBuilder);
|
|
|
|
// Make the TypeInfo real so the constructor can be used.
|
|
return attributeTypeBuilder.CreateTypeInfo()!.DeclaredConstructors.Single();
|
|
}
|
|
}
|
|
}
|