Tôi nghĩ bạn có thể làm điều này bằng cách sử dụng thuộc tính tùy chỉnh và phân tích mã roslyn. Hãy để tôi phác thảo một giải pháp. Điều này ít nhất nên giải quyết các usecase đầu tiên, nơi bạn khởi tạo với một chữ.
Trước tiên, bạn sẽ cần một thuộc tính tùy chỉnh áp dụng cho cấu trúc của bạn để cho phép các mã phân tích để có thể biết được phạm vi hợp lệ:
[AttributeUsage(System.AttributeTargets.Struct)]
public class MinMaxSizeAttribute : Attribute
{
public int MinVal { get; set;}
public int MaxVal { get; set;}
public MinMaxSizeAttribute()
{
}
}
Những gì bạn làm ở đây là bạn lưu trữ các giá trị min và max trong một thuộc tính. Bằng cách đó bạn có thể sử dụng sau này trong các phân tích mã nguồn.
Bây giờ áp dụng thuộc tính này để khai báo struct:
[MinMaxSize(MinVal = 0, MaxVal = 100)]
public struct Foo
{
//members and implicit conversion operators go here
}
Bây giờ những thông tin kiểu cho các struct Foo
chứa nhiều giá trị. Điều tiếp theo bạn cần là DiagnosticAnalyzer
để phân tích mã của bạn.
public class MyAnalyzer : DiagnosticAnalyzer
{
internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor("CS00042",
"Value not allowed here",
@"Type {0} does not allow Values in this range",
"type checker",
DiagnosticSeverity.Error,
isEnabledByDefault: true, description: "Value to big");
public MyAnalyzer()
{
}
#region implemented abstract members of DiagnosticAnalyzer
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeSyntaxTree, SyntaxKind.SimpleAssignmentExpression);
}
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
#endregion
private static void AnalyzeSyntaxTree(SyntaxNodeAnalysisContext context)
{
}
}
Đây là bộ xương xương trần tham gia phân tích mã. Máy phân tích đăng ký để phân tích bài tập:
context.RegisterSyntaxNodeAction(AnalyzeSyntaxTree, SyntaxKind.SimpleAssignmentExpression);
Đối với khai báo biến bạn sẽ cần phải đăng ký một khác nhau SyntaxKind
nhưng vì đơn giản tôi sẽ dính vào ai ở đây.
Cho phép có một cái nhìn tại các phân tích logic:
private static void AnalyzeSyntaxTree(SyntaxNodeAnalysisContext context)
{
if (context.Node.IsKind(SyntaxKind.SimpleAssignmentExpression))
{
var assign = (AssignmentExpressionSyntax)context.Node;
var leftType = context.SemanticModel.GetTypeInfo(assign.Left).GetType();
var attr = leftType.GetCustomAttributes(typeof(MinMaxSizeAttribute), false).OfType<MinMaxSizeAttribute>().FirstOrDefault();
if (attr != null && assign.Right.IsKind(SyntaxKind.NumericLiteralExpression))
{
var numLitteral = (LiteralExpressionSyntax)assign.Right;
var t = numLitteral.Token;
if (t.Value.GetType().Equals(typeof(int)))
{
var intVal = (int)t.Value;
if (intVal > attr.MaxVal || intVal < attr.MaxVal)
{
Diagnostic.Create(Rule, assign.GetLocation(), leftType.Name);
}
}
}
}
}
gì phân tích thực hiện là, đang kiểm tra nếu loại ở phía bên trái có một MinMaxSize
liên kết với nó và nếu như vậy nó sẽ kiểm tra nếu phía bên phải là một chữ. Khi nó là một chữ, nó cố gắng lấy giá trị số nguyên và so sánh nó với các số MinVal
và MaxVal
được kết hợp với loại. Nếu các giá trị vượt quá phạm vi đó, nó sẽ báo cáo lỗi chẩn đoán.
Xin lưu ý rằng tất cả mã này hầu như không được kiểm tra. Nó biên dịch và thông qua một số bài kiểm tra cơ bản. Nhưng nó chỉ có nghĩa là để minh họa một giải pháp có thể. Để biết thêm thông tin, hãy xem Rsolyn Docs
Trường hợp thứ hai bạn muốn bao gồm phức tạp hơn vì bạn sẽ cần phải áp dụng dataflow analyzes để nhận giá trị x
.
không thể thực hiện được. byte là một loại với phạm vi 255. tôi không nghĩ rằng bạn có thể giới hạn này trong thời gian biên dịch hoặc để tạo kiểu tùy chỉnh. –
@M.kazemAkhgary Nó có thể có được bằng cách sửa đổi Roslyn, mặc dù tôi không chắc chắn làm thế nào cứng hoặc hợp lý mà có thể là –
Câu hỏi thú vị! Trong Visual Studio 2013, nếu tôi đặt một giá trị bằng chữ quá lớn, thì Intellisense sẽ biết. Tôi tự hỏi nếu có một cách để xác định một lớp học với sự hỗ trợ Intellisense tương tự hoặc nếu đó là nướng trong. –