Crie um atributo para quebrar a compilação
-
09-06-2019 - |
Pergunta
OK, isso segue de minha pergunta anterior.
O que eu realmente gostaria de fazer é criar algum tipo de atributo que me permita decorar um método que irá quebrar a construção.Muito parecido com o Obsoleto("motivo", verdadeiro) atributo, mas sem identificar falsamente código obsoleto.
Esclarecer:Eu não quero que isso quebre a construção QUALQUER Pressione F6 (Build), só quero interromper a compilação se um método decorado com o atributo for chamado em algum outro lugar do código.Como eu disse, semelhante obsoleto, mas não o mesmo.
Eu sei que não estou sozinho nisso, pois outros usuários desejam usá-lo por outros motivos.Nunca criei atributos personalizados antes, então é tudo novo para mim!
Solução
Se for para serialização XML e NHibernate, onde você deseja que o construtor sem parâmetros seja acessível (como é o caso no exemplo você referenciou), então use um construtor sem parâmetros privado ou protegido para serialização ou um construtor protegido para NHibernate.Com a versão protegida, você está se abrindo para que classes herdadas possam chamar esse código.
Se você não quiser que o código chame um método, não o torne acessível.
EDITAR:Talvez para responder à questão mais profunda, o compilador AFAIK conhece apenas três atributos: Obsoleto, condicional e uso de atributos.Adicionar tratamento especial para outros atributos exigiria a modificação do compilador.
Outras dicas
Acho que esta seria uma excelente solicitação de recurso para a Microsoft:Crie um atributo abstrato de classe base CompilerExecutedAttribute
que o compilador processa de alguma maneira ou que pode influenciar o processo de compilação.Então poderíamos herdar deste atributo e implementar diferentes operações, por ex.emitir um erro ou um aviso.
Acho que a única maneira infalível seria estender o Visual Studio (por meio de VSIP) e assinar o evento correto (talvez na classe EnvDTE.BuildEvents), verificar seu código para uso do construtor e cancelar a compilação se você detectá-lo.
Tudo isso está começando a soar um pouco como TDWTF de ontem. :-)
Terei que concordar com Greg:crie um atributo para ele.
E se você estiver realmente falando sério, talvez encontre uma maneira de descobrir se o construtor está sendo acessado por algo diferente de XMLSerializer e lançar uma exceção, se estiver.
Eu sugiro que você use a diretiva #error.
Outro atributo bastante desconhecido que pode fazer o trabalho é o atributo condicional (dependendo do que você está tentando alcançar)
[Conditional("CONDITION")]
public static void MiMethod(int a, string msg)
que removerá a invocação do método do próprio código IL se "MY_CONDITION" for definido.
Crie uma regra FxCop e adicione FxCop à sua construção de integração para verificar isso.
Você receberá avisos, em vez de uma compilação com falha.Os atributos são executados no momento da reflexão, e não no momento da construção.
Alternativamente (e isso é bastante desagradável) coloque uma diretiva do compilador em torno do método que você não deseja que seja chamado.Então seu código será quebrado se você chamá-lo, mas você pode configurar uma compilação que passe a diretiva correta do compilador e não o faça.
Lançar uma exceção personalizada e um teste de unidade como uma etapa pós-construção
Respondendo 4 anos depois :)
Eu tive a mesma pergunta se houvesse uma alternativa ao Obsoleto.
Pelo que me lembro (vídeos do canal 9), há pouco tempo, a Microsoft afirmou que está trabalhando para dar aos desenvolvedores acesso a algo como uma API de compilador em algum momento, então no futuro é concebível que você possa escrever um "plugin" de compilador que permitiria para decorar métodos com seu próprio atributo personalizado e dizer ao compilador para cancelar se parecer que o código decorado pode estar sendo chamado em algum outro lugar do código, etc.
O que seria realmente muito legal quando você pensa sobre isso.Isso também me lembra que eu também deveria tentar ler sobre o progresso daquela API do compilador em que a MS está trabalhando ...
Por que não inventar algo?Um atributo desconhecido certamente quebraria a construção.
[MyMadeUpAttributeThatBreaksTheBuildForSure]
public class NotDoneYet {}