Search code examples
c#aopfody

Fody: Copy an attribute from one property to another


I iterate through all classes, then all properties, then their attributes. When I see an attribute MetaAttribute(typeof(SomethingElse)) I find a property named Target on that class and copy all of its properties across to the current property on the class in the module being worked on by the weaver...

For example

public class Person
{
  [Meta(typeof(PersonTitleMeta))] // <- Identifies the source
  public string Title { get; set; } // <- The target property
}

public class PersonTitleMeta
{
  [Required, MinimumLength(2), MaximumLength(16)] // These get applied to Person.Title
  public object Target { get; set; }
}

This works fine when the PersonTitleMeta is in the same assembly as Person

foreach (var currentSourceAttribute in sourceAttributes)
    property.CustomAttributes.Add(currentSourceAttribute);

But when they are in different assemblies it does not work System.ComponentModel.DataAnnotations.RequiredAttribute::.ctor()' is declared in another module and needs to be imported

Could someone please tell me how to copy the attribute across from a different assembly?


Solution

  • This seems to be doing the trick, but is it the correct way to do it?

            private CustomAttribute CloneAttribute(CustomAttribute sourceAttribute)
            {
                MethodReference sourceAttributeConstructor = sourceAttribute.Constructor;
                MethodReference localAttributeConstructorReference = ModuleDefinition.ImportReference(sourceAttributeConstructor);
    
                var localCustomAttribute = new CustomAttribute(localAttributeConstructorReference);
                foreach (var sourceAttributeConstructorArgument in sourceAttribute.ConstructorArguments)
                {
                    TypeReference localAttributeTypeReference = sourceAttributeConstructorArgument.Type;
                    CustomAttributeArgument localAttributeInstance = new CustomAttributeArgument(localAttributeTypeReference, sourceAttributeConstructorArgument.Value);
                    localCustomAttribute.ConstructorArguments.Add(localAttributeInstance);
                }
    
                return localCustomAttribute;
            }