Using Reflection.Emit to Copy a Custom Attribute to Another Method

I am trying to create a new set of wcf interfaces based on existing interfaces. I am using the Reflection.Emit namespace to accomplish this. My problem is how to copy the old user attributes from one method to the new. Each example that I saw in SetCustomAttributes () requires knowledge of the attribute type in advance. I need to know the type of attribute at runtime. Any suggestions?

+4
source share
4 answers

The answer you (frjames) posted is close, but does not account for property initializers such as ...

[ServiceBehavior(Name="ServiceName")] 

However, the idea of โ€‹โ€‹converting CustomAttributeData to CustomAttributeBuilder for use in Reflection.Emit is implemented correctly.

I had to do this for an open source project (Autofac) and came up with this extension method:

 public static CustomAttributeBuilder ToAttributeBuilder(this CustomAttributeData data) { if (data == null) { throw new ArgumentNullException("data"); } var constructorArguments = new List<object>(); foreach (var ctorArg in data.ConstructorArguments) { constructorArguments.Add(ctorArg.Value); } var propertyArguments = new List<PropertyInfo>(); var propertyArgumentValues = new List<object>(); var fieldArguments = new List<FieldInfo>(); var fieldArgumentValues = new List<object>(); foreach (var namedArg in data.NamedArguments) { var fi = namedArg.MemberInfo as FieldInfo; var pi = namedArg.MemberInfo as PropertyInfo; if (fi != null) { fieldArguments.Add(fi); fieldArgumentValues.Add(namedArg.TypedValue.Value); } else if (pi != null) { propertyArguments.Add(pi); propertyArgumentValues.Add(namedArg.TypedValue.Value); } } return new CustomAttributeBuilder( data.Constructor, constructorArguments.ToArray(), propertyArguments.ToArray(), propertyArgumentValues.ToArray(), fieldArguments.ToArray(), fieldArgumentValues.ToArray()); } 

In this case, all methods of attribute initialization are taken into account.

+5
source

Here is the answer that I came up with after several studies.

 CustomAttributeBuilder ct = AddAttributesToMemberInfo(methodInfo); if (ct != null) { methodBuilder.SetCustomAttribute(ct); } CustomAttributeBuilder AddAttributesToMemberInfo(MemberInfo oldMember) { CustomAttributeBuilder ct = null; IList<CustomAttributeData> customMethodAttributes = CustomAttributeData.GetCustomAttributes(oldMember); foreach (CustomAttributeData att in customMethodAttributes) { List<object> namedFieldValues = new List<object>(); List<FieldInfo> fields = new List<FieldInfo>(); List<object> constructorArguments = new List<object>(); foreach (CustomAttributeTypedArgument cata in att.ConstructorArguments) { constructorArguments.Add(cata.Value); } if (att.NamedArguments.Count > 0) { FieldInfo[] possibleFields = att.GetType().GetFields(); foreach (CustomAttributeNamedArgument cana in att.NamedArguments) { for (int x = 0; x < possibleFields.Length; x++) { if (possibleFields[x].Name.CompareTo(cana.MemberInfo.Name) == 0) { fields.Add(possibleFields[x]); namedFieldValues.Add(cana.TypedValue.Value); } } } } if (namedFieldValues.Count > 0) { ct = new CustomAttributeBuilder(att.Constructor, constructorArguments.ToArray(), fields.ToArray(), namedFieldValues.ToArray()); } else { ct = new CustomAttributeBuilder(att.Constructor, constructorArguments.ToArray()); } } return ct; } 
+2
source

The code from Travis Illig needs to be adjusted, as shown below, to work with .Net Core:

 foreach (var namedArg in data.NamedArguments) { string argName = namedArg.MemberName; var fi = data.AttributeType.GetField(argName); var pi = data.AttributeType.GetProperty(argName); 
+1
source

try the following:

 MethodInfo mi; //... object[] custAttribs = mi.GetCustomAttributes(false); foreach (object attrib in custAttribs) attrib.GetType(); 

I assume you have MethodInfo for your methods

0
source

Source: https://habr.com/ru/post/1302893/


All Articles