C# 如何使用Roslyn更改属性
我努力在roslyn库中找到正确的方法来更改属性并重写属性:C# 如何使用Roslyn更改属性,c#,roslyn,custom-attributes,C#,Roslyn,Custom Attributes,我努力在roslyn库中找到正确的方法来更改属性并重写属性: class Program { static void Main(string[] args) { //this is the original class var str = @"public class OfferModel { public int Id { get; set; } [Required(Erro
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;
}
}
这同样适用于[Display]/[Range]属性。如果我能使[必需]工作,我可以将其应用于[显示]/[范围]您的最后一行是:
newNode=node.ReplaceNode(node,newAttribute)
看起来您只是试图用不同的实例(newAttribute)替换子树(节点)的根。ReplaceNode无法在根节点上工作。相反,您应该只使用新节点
应该是:
newNode=newAttribute 您当前的代码究竟是如何失败的?如果调试代码,在什么情况下其行为会变得与您期望的不同?上面的代码生成如下属性:[Required(ErrorMessageResourceName)]它应该是:[Required(ErrorMessageResourceType=typeof(WebModels),ErrorMessageResourceName=“Required”)]
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; }
}