2017-07-10 5 views
1

je lutte pour trouver les bonnes méthodes sur la bibliothèque Roslyn pour apporter des modifications aux attributs et réécrire l'attribut:Comment modifier les attributs avec Roslyn

class Program 
{ 
    static void Main(string[] args) 
    { 

     //this is the original class 
     var str = @"public class OfferModel 
     { 
      public int Id { get; set; } 

      [Required(ErrorMessage = \""Required\"")] 
      [Display(Name = \""Date of Offer *\"")] 
      public DateTime? OfferDate { get; set; } 

      [Required(ErrorMessage = \""Required\"")] 
      [Display(Name = \""Amount *\"")] 
      [Range(1, double.MaxValue, ErrorMessage = \""Invalid Amount\"")] 
      public decimal? Amount { get; set; } 
     }"; 

     var tree = CSharpSyntaxTree.ParseText(str); 

     var myWriter = new MyReWriter(); 
     var newRoot = myWriter.Visit(tree.GetRoot()); 

     Console.WriteLine(newRoot.ToFullString()); 

    } 
} 

public class MyReWriter : CSharpSyntaxRewriter 
{ 
    public MyReWriter() : base() { } 

    public override SyntaxNode VisitAttribute(AttributeSyntax node) 
    { 
     var newNode = node; 

     if (node.Name.ToString() == "Required") 
     { 
      newNode = PrepareNewRequiredArgument(node); 
     } 

     return base.VisitAttribute(newNode); 
    } 

    private AttributeSyntax PrepareNewRequiredArgument(AttributeSyntax node) 
    { 
     var newNode = node; 
     //ErrorMessageResourceType 
     //ErrorMessageResourceName 
     var argResType = node.ArgumentList.Arguments.FirstOrDefault(aa => aa.NameEquals.Name.Identifier.Text == "ErrorMessageResourceType"); 
     var argResName = node.ArgumentList.Arguments.FirstOrDefault(aa => aa.NameEquals.Name.Identifier.Text == "ErrorMessageResourceName"); 
     if (argResType != null && argResName != null) 
     { 
      //already exists, don't do anything 
      return newNode; 
     } 

     var argErrorMessage = node.ArgumentList.Arguments.FirstOrDefault(aa => aa.NameEquals.Name.Identifier.Text == "ErrorMessage"); 

     if (argErrorMessage != null) 
     { 
      var name = ParseName("Required"); 
      var tokenValue = ((LiteralExpressionSyntax)argErrorMessage.Expression).Token.Value; 

      var argErrorMessageResourceName = AttributeArgument(
       LiteralExpression(SyntaxKind.StringLiteralExpression, 
        Token(default(SyntaxTriviaList), 
          SyntaxKind.StringLiteralToken, "ErrorMessageResourceName", tokenValue.ToString(), default(SyntaxTriviaList)))); 

      //var argErrorMessageResourceType = AttributeArgument(
      // LiteralExpression(SyntaxKind.NumericLiteralExpression, 
      //  Token(default(SyntaxTriviaList), 
      //    SyntaxKind.NumericLiteralToken, "ErrorMessageResourceType", "typeof(WebModels)", default(SyntaxTriviaList)))); 

      var otherList = new SeparatedSyntaxList<AttributeArgumentSyntax>(); 
      otherList = otherList.AddRange(new[] { argErrorMessageResourceName }); 
      //otherList = otherList.AddRange(new[] { argErrorMessageResourceName, argErrorMessageResourceType }); 
      var argumentList = AttributeArgumentList(otherList); 
      var newAttribute = Attribute(name, argumentList); 

      newNode = node.ReplaceNode(node, newAttribute); 
     } 
     return newNode; 
    } 
} 

La sortie que je requiers doit ressembler à suivre:

public class OfferModel 
{ 
    public int Id { get; set; } 

    [Required(ErrorMessageResourceType = typeof(WebModels), ErrorMessageResourceName = \""Required\"")] 
    [Display(Name = \""Date of Offer *\"")] 
    public DateTime? OfferDate { get; set; } 

    [Required(ErrorMessageResourceType = typeof(WebModels), ErrorMessageResourceName = "Required")] 
    [Display(ResourceType = typeof(WebModels), Name = "Amount *")] 
    [Range(1, double.MaxValue, ErrorMessageResourceName = "InvalidAmount")] 
    public decimal? Amount { get; set; } 
} 

La même chose s'applique pour les attributs [Display]/[Range]. Si je peux obtenir le [Obligatoire] pour travailler, je peux appliquer la même chose à [Affichage]/[Plage]

+0

Comment exactement votre code actuel échoue-t-il? Si vous déboguez votre code, à quel moment son comportement n'est-il pas ce que vous attendez? – svick

+0

Le code ci-dessus génère l'attribut comme suit: [Obligatoire (ErrorMessageResourceName)] Il devrait être: [Obligatoire (ErrorMessageResourceType = typeof (WebModels), ErrorMessageResourceName = "Obligatoire")] –

Répondre

0

Votre dernière ligne est:

newNode = node.ReplaceNode (noeud, newAttribute);

il semble que vous essayez simplement de remplacer la racine d'un sous-arbre (noeud) par une instance différente (nouvelAttribut). ReplaceNode ne fonctionnera pas sur le noeud racine. Au lieu de cela, vous devriez simplement utiliser le nouveau noeud.

il devrait juste être:

newNode = newAttribute;