Fiz uma class de gerador que constrói uma class de proxy baseada na interface que implementa a interface.
Veja minha postagem em Criar uma class de proxy com base na interface sem implementá-la .
Estou familiarizado com CustomAttributeData.GetCustomAttributes(MemberInfo target)
, usei-o quando li os membros da Interface e consegui importá-los para o proxy.
Eu quero injetar atributos adicionais para a class gerada em tempo de execução. Estou pedindo instâncias de atributos para injetá-los no proxy.
Por exemplo:
Um desenvolvedor pode passar isso como um valor: new ObsoleteAttribute("Demo", true)
, (ele tem um construtor vazio, mas as propriedades são somente leitura), e eu quero convertê-lo para:
return new CustomAttributeBuilder( attribute.GetType().GetConstructor(Type[] {typeof (string), typeof (bool)}), new object[] {"Demo", true}, new FieldInfo[0], new object[0]);
Lembre-se, não posso dizer o que é dado.
Esta não é uma solução geral, mas funcionará se você estiver disposto a restringir os atributos que você suporta àqueles com construtores sem parâmetros e propriedades e campos de leitura / gravação.
CustomAttributeBuilder BuildCustomAttribute(System.Attribute attribute) { Type type = attribute.GetType(); var constructor = type.GetConstructor(Type.EmptyTypes); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); var propertyValues = from p in properties select p.GetValue(attribute, null); var fieldValues = from f in fields select f.GetValue(attribute); return new CustomAttributeBuilder(constructor, Type.EmptyTypes, properties, propertyValues.ToArray(), fields, fieldValues.ToArray()); }
Para fazer uma solução geral, você poderia usar expressões. Isso é mais complicado, mas permitiria uma syntax como:
BuildCustomAttribute(() => new ObsoleteAttribute("Demo", true));
Analisando a expressão para extrair as informações do construtor e os parâmetros seriam a parte complexa, mas isso pode ser feito.
CustomAttributeBuilder BuildCustomAttribute(Expression exp) { //extract ConstructorInfo from exp //extract ParameterValues from exp //extract Attribute Type from exp return new CustomAttributeBuilder(ConstructorInfo, ParameterValues); }
Obrigado Joe,
Eu encontrei a solução Expression
no Attribute Builder , graças à sua input.
Estou disposto a trabalhar um pouco mais agora para tornar outros desenvolvedores mais fáceis de usar o meu proxy .
Eu esperava que poderia ser mais fácil, e se eu tenho a instância do atributo, por que não posso usá-lo como está e aplicar o atributo?
Se você tiver uma solução sem Expression
, adoraria saber disso.
Aqui está a minha solução com o Expression
baseado no Attribute Builder :
private CustomAttributeBuilder GetCustumeAttributeBuilder(Expression> attributeExpression) { ConstructorInfo constructor = null; List
Se eu entendi a pergunta corretamente, isso deve adicionar um atributo personalizado ao tipo gerado
public class CustomAttribute: System.Attribute { public CustomAttribute() { } } TypeBuilder typeBuilder = module.DefineType(...)
….
typeBuilder.SetCustomAttribute(new CustomAttributeBuilder( typeof(CustomAttribute).GetConstructor(Type.EmptyTypes), Type.EmptyTypes, new FieldInfo[0], new object[0]));