SyntaxNode.ContainsDiagnostics not working with your own diagnostics? - c#

I am trying to write an analyzer that prevents users from providing parameters that are automatically provided (ex: by the compiler with [CallerMemberName]) and I want the analyzer to error you when you have provided a parameter that shouldn't be provided (to tell a parameter shouldn't be provided I created an attribute : DontProvideAttribute).
The thing is such automatically provided parameters must be optional (otherwise the value provided by the user would be written over the one provided automatically) so I've made a second analyze to prevent users from using [DontProvide] on non-optional parameters.
And there comes the problem, I want the error on the method invocation to be there only if the parameter declaration doesn't have the [DontProvide] should only be used on optional parameters error which
foreach (SyntaxReference parameterDefinition in parameter.DeclaringSyntaxReferences)
{
if (parameterDefinition.GetSyntax().ContainsDiagnostics)
{
return;
}
}
should complete this but it seems like it doesn't consider diagnostics you reported yourself.
What i have tried :
-Changing the order of diagnostics to make the declaration being analyzed before the method invocation
-Use .GetDiagnostics().Count() > 0 instead
-Changing the order of the text in the analyzed document to have the method declaration above the method invocation
The analyzer :
public override void Initialize(AnalysisContext context)
{
context.RegisterSymbolAction(AnalyzeParametersDeclaration, SymbolKind.Parameter);
context.RegisterOperationAction(AnalyzeArguments, OperationKind.Argument);
}
private void AnalyzeArguments(OperationAnalysisContext context)
{
IArgumentOperation reference = (IArgumentOperation)context.Operation;
IParameterSymbol parameter = reference.Parameter;
foreach (SyntaxReference parameterDefinition in parameter.DeclaringSyntaxReferences)
{
if (parameterDefinition.GetSyntax().ContainsDiagnostics)
return;
}
foreach (AttributeData attribute in parameter.GetAttributes())
{
if (attribute.AttributeClass.Name == "DontProvideAttribute")
{
context.ReportDiagnostic(Diagnostic.Create(DontProvide, reference.Syntax.GetLocation(), parameter.Name));
}
}
}
private void AnalyzeParametersDeclaration(SymbolAnalysisContext context)
{
IParameterSymbol parameter = (IParameterSymbol)context.Symbol;
if (parameter.GetAttributes().Any(a => a.AttributeClass.Name == "DontProvideAttribute") && !parameter.IsOptional)
{
context.ReportDiagnostic(Diagnostic.Create(DontProvideOnlyForOptional, parameter.Locations[0]))
}
}
Some test code for analyze :
using System;
namespace test
{
internal class Program
{
private static void Main(string[] args)
{
MyClass.MyMethod(null);
}
}
internal class MyClass
{
public static void MyMethod([DontProvide] object parameter)
{
}
}
[AttributeUsage(AttributeTargets.Parameter)]
public class DontProvideAttribute : Attribute
{
}
}
PS : The compiler may tell you that context.RegisterSymbolAction() used with SymbolKind.Parameter isn't supported, which is wrong (see more here)

From the discussion here and #Kris Vandermotten's comment
ContainsDiagnostics is only for syntactic diagnostics (i.e. diagnostics acutally inside the syntax tree)
not for diagnostics reported by later passes (i.e. semantic diagnostics or your own analyzer diagnostics).
Here's why : a specific syntax tree may be contained in many different semantic contexts due to roslyn being able to fork and speculate about things
so in one context, the syntax may be semantically correct, and in another, it won't be
as such, the diagnostics are not stored on the tree itself.
In fact the solution in my case was pretty simple : i just had to remove
foreach (SyntaxReference parameterDefinition in parameter.DeclaringSyntaxReferences)
{
if (parameterDefinition.GetSyntax().ContainsDiagnostics)
return;
}
and add && parameter.IsOptionnal on the if statement there :
foreach (AttributeData attribute in parameter.GetAttributes())
{
if (attribute.AttributeClass.Name == "DontProvideAttribute")
{
context.ReportDiagnostic(Diagnostic.Create(DontProvide, reference.Syntax.GetLocation(), parameter.Name));
}
}

Related

Determining if a private field is read using Roslyn

I've been searching all day and have read many posts but I just can't quite come to a conclusion on this. I'm trying to create a Roslyn analyzer to report a diagnostic when a private field is unread. Registering the syntax action and finding out if its private was really easy. But now I'm stuck on trying to find out if the field is read in the class.
Assume we have the following example code:
public class C {
private int foo; //private field is declared but never read. Should report diagnostic here
public void DoNothing() {
//irrelevant
}
}
There are several examples of where I'd want this flagged (initialized or not, injected or not, multiple declarations on single line, etc.), but I think maybe they're not necessary for illustrating the question.
What I have so far is this:
public override void Initialize(AnalysisContext context) {
context.EnableConcurrentExecution();
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.RegisterSyntaxNodeAction(AnalyzeField, SyntaxKind.FieldDeclaration);
}
private void AnalyzeField(SyntaxNodeAnalysisContext context) {
if (!(context.Node is FieldDeclarationSyntax fieldDeclarationSyntax)) {
return;
}
foreach (var variableDeclaration in fieldDeclarationSyntax.Declaration.Variables) {
if (context.SemanticModel.GetDeclaredSymbol(variableDeclaration) is IFieldSymbol variableDeclarationSymbol &&
IsFieldPrivate(variableDeclarationSymbol) &&
!IsFieldRead(context, variableDeclarationSymbol)) {
//report diagnostic here
}
}
}
private bool IsFieldPrivate(IFieldSymbol fieldSymbol) {
return fieldSymbol.DeclaredAccessibility == Accessibility.Private || // the field itself is explicitly private
fieldSymbol.ContainingType?.DeclaredAccessibility == Accessibility.Private; //the field is not private, but is contained within a private class
}
private bool IsFieldRead(SyntaxNodeAnalysisContext context, IFieldSymbol fieldSymbol) {
//context.Node.Parent will be the class declaration here since we're analyzing a field declaration
//but let's be safe about that just in case and make sure we traverse up until we find the class declaration
var classDeclarationSyntax = context.Node.Parent;
while (!(classDeclarationSyntax is ClassDeclarationSyntax)) {
classDeclarationSyntax = classDeclarationSyntax.Parent;
}
var methodsInClassContainingPrivateField = classDeclarationSyntax.DescendantNodes().OfType<MethodDeclarationSyntax>().ToImmutableArray();
foreach (var method in methodsInClassContainingPrivateField) {
var dataFlowAnalysis = context.SemanticModel.AnalyzeDataFlow(method); //does not work because this is not a StatementSyntax or ExpressionSyntax
if (dataFlowAnalysis.ReadInside.Contains(fieldSymbol) || dataFlowAnalysis.ReadOutside.Contains(fieldSymbol)) {
return true;
}
}
return false;
}
I just can't quite figure out how to get the IsFieldRead() method to work. This really feels like something that should be easy to do but I just can't quite wrap my head around it. I figured getting the methods and analyzing those for my field to see if it was read would be a decent idea, but that doesn't cover if the field is read by another private field, and I can't get it working anyway. :)
I managed to get this figured out thanks to this other SO answer by someone who actually works on Roslyn at Microsoft. Here is my IsFieldRead() method now. The key apparently lied in the Microsoft.CodeAnalysis.Operations namespace.
private bool IsFieldRead(SyntaxNodeAnalysisContext context, IFieldSymbol fieldSymbol) {
var classDeclarationSyntax = context.Node.Parent;
while (!(classDeclarationSyntax is ClassDeclarationSyntax)) {
classDeclarationSyntax = classDeclarationSyntax.Parent;
if (classDeclarationSyntax == null) {
throw new InvalidOperationException("You have somehow traversed up and out of the syntax tree when determining if a private member field is being read.");
}
}
//get all methods in the class
var methodsInClass = classDeclarationSyntax.DescendantNodes().OfType<MethodDeclarationSyntax>().ToImmutableArray();
foreach (var method in methodsInClass) {
//get all member references in those methods
if (context.SemanticModel.GetOperation(method).Descendants().OfType<IMemberReferenceOperation>().ToImmutableArray().Any(x => x.Member.Equals(fieldSymbol))) {
return true;
}
}
return false;
}
Note that this only covers usages within methods. There are several other places like other fields, properties, and constructors that would also need to be checked.

.NET Core: attributes that execute before and after method

In Java, it is possible to use AspectJ for adding behavior before and after executing a method, using method annotations. Since C# Attributes seem to be very similar, I was wondering whether it would be possible to achieve similar behavior. I was looking in several tutorials and other sources (1, 2, 3), but none of them helped me.
I thought that maybe I could be able to mimic the behavior by inserting the code into Attribute constructor and making it disposable, like this:
[AttributeUsage(AttributeTargets.Method)]
public class MyWritingAttribute : Attribute, IDisposable
{
public MyWritingAttribute()
{
Console.WriteLine("Attribute created");
}
public void Dispose()
{
Console.WriteLine("Attribute disposed");
}
}
However, when using the attribute like this, only Hello world! got displayed in the console:
class Program
{
static void Main(string[] args)
{
SayHelloWorld();
Console.ReadLine();
}
[MyWriting]
private static void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}
}
I was thinking that maybe Console is not reachable in the attribute, but even when replacing it with throw new Exception() expressions, no exception was thrown. How is it possible that StringLengthAttribute from EF works, but my attribute is not even instantiated? And how do I make the attribute run before and after the decorated method?
You need some framework that is able to handle your attribute appropriately. Only because the attribute exists doesn´t mean it will have any affect.
I wrote some easy engine that does that. It will determine if the attribute is present on the passed action and if so get the reflected methods in order to execute them.
class Engine
{
public void Execute(Action action)
{
var attr = action.Method.GetCustomAttributes(typeof(MyAttribute), true).First() as MyAttribute;
var method1 = action.Target.GetType().GetMethod(attr.PreAction);
var method2 = action.Target.GetType().GetMethod(attr.PostAction);
// now first invoke the pre-action method
method1.Invoke(null, null);
// the actual action
action();
// the post-action
method2.Invoke(null, null);
}
}
public class MyAttribute : Attribute
{
public string PreAction;
public string PostAction;
}
Of course you need some null-ckecks, e.g. in the case the methods don´t exist or aren´t static.
Now you have to decorate your action with the attribute:
class MyClass
{
[MyAttribute(PreAction = "Handler1", PostAction = "Handler2")]
public void DoSomething()
{
}
public static void Handler1()
{
Console.WriteLine("Pre");
}
public static void Handler2()
{
Console.WriteLine("Post");
}
}
Finally you can execute that method within our engine:
var engine = new Engine();
var m = new MyClass();
engine.Execute(m.DoSomething);
Just like with Java and AspectJ, you need separate AoP tooling to inject code like this in .NET.
PostSharp is one such tool, probably the best known. I belive they have support for .NET core since version 5.
This can be accomplished using DynamicProxy.
There is an implementation of a memory caching technique with logic that executes before the method being called. That can be extended to check for the existence of an attribute like this
var attribute = Attribute.GetCustomAttribute(invocation.MethodInvocationTarget, typeof(CachedAttribute)) as CachedAttribute;
if (attribute != null)
{
...
}
The code above can be inside the Intercept method in the Interceptor implementation. CachedAttribute would be your attribute.
The question is similar to Run a method before all methods of a class, hence the same answer applies to both.
Use https://github.com/Fody/Fody . The licencing model is based on voluntary contributions making it the better option to PostSharp which is a bit expensive for my taste.
[module: Interceptor]
namespace GenericLogging
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Assembly | AttributeTargets.Module)]
public class InterceptorAttribute : Attribute, IMethodDecorator
{
// instance, method and args can be captured here and stored in attribute instance fields
// for future usage in OnEntry/OnExit/OnException
public void Init(object instance, MethodBase method, object[] args)
{
Console.WriteLine(string.Format("Init: {0} [{1}]", method.DeclaringType.FullName + "." + method.Name, args.Length));
}
public void OnEntry()
{
Console.WriteLine("OnEntry");
}
public void OnExit()
{
Console.WriteLine("OnExit");
}
public void OnException(Exception exception)
{
Console.WriteLine(string.Format("OnException: {0}: {1}", exception.GetType(), exception.Message));
}
}
public class Sample
{
[Interceptor]
public void Method(int test)
{
Console.WriteLine("Your Code");
}
}
}
[TestMethod]
public void TestMethod2()
{
Sample t = new Sample();
t.Method(1);
}

Making extension methods from a third party library obsolete

This question is not about a method I can mark with [System.Obsolete]. The method I wanna ignore is in a dll I don't have control over.
I use a 3rd party library which contains an extension method for objects. This leads to confusion and may cause problems in the future.
Is there any way to mark this extension method (or all the extension methods from a certain dll ) as obsolete externally or prevent this extension method appearing in intellisense. The problematic method is :
public static class ExtensionMethods
{
public static bool IsNumeric(this object obj)
{
if (obj == null)
return false;
return obj.GetType().IsPrimitive || obj is double || (obj is Decimal || obj is DateTime) || obj is TimeSpan;
}
}
You can do this with a Roslyn Code Analyzer. The following code will create a DiagnosticAnalyzer that will give a compiler warning if String.EndsWith() is used.
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class ForbiddenMethodsAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor("Forbidden",
"Don't use this method!",
"Use of the '{0}' method is not allowed",
"Forbidden.Stuff",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "This method is forbidden");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression);
}
private static void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context)
{
var invocationExpression = (InvocationExpressionSyntax)context.Node;
var memberAccessExpression = invocationExpression.Expression as MemberAccessExpressionSyntax;
if (memberAccessExpression?.Name.ToString() == "EndsWith")
{
var memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccessExpression).Symbol as IMethodSymbol;
var containingType = memberSymbol.ContainingType;
if (containingType.ContainingNamespace.Name == "System" && containingType.Name == "String")
{
var diagnostic = Diagnostic.Create(Rule, invocationExpression.GetLocation(), memberAccessExpression.ToString());
context.ReportDiagnostic(diagnostic);
}
}
}
}
There are 3 options to use an Analyzer like this:
Add the DiagnosticAnalyzer code directly to your project. It will apply only to that solution.
Create a
class library with the DiagnosticAnalyzer in it, and distribute it
as a Nuget package. It will apply only to solutions that use the package.
Compile a full VSIX extension containing the
class. The analyzer will work on any solution you load.
This is the first project I've done that uses the Roslyn Code Analysis functionality, so unfortunately I don't understand everything that is going on here. I started with the default Analyzer template and tried various methods, stepped through code, and looked at variables with the watch windows until I found the information I needed for this functionality.
The basic process is to register a SyntaxNode Analysis function, filtered to expressions that invoke a method. Within that method I check to see if the Name of the MemberAccessExpressionSyntax being examined is "EndsWith". If it is, I get the ContainingType that the method is on, and check to see if it is on the String class in the System namespace. If it is, I create a Diagnostic instance from a DiagnosticDescriptor to tell the IDE where the problem is, and how much of a problem it represents (A warning in this case, I could make it a full Error if I wanted, which would prevent the code from compiling). It is also possible to present the user with different options to automatically fix the error, but I haven't explored that yet.
A lot of the information came from this tutorial, as well as a whole lot of trial and error.
The best way to handle this would be to use Roslyn and create your own code analyzer, or use an existing tool like FxCop.
However, I found a very non-elegant workaround for this.
In your project you can create a class with the same name as the referenced class, residing in an identical namespace, with the exact same method. Now mark your method as obsolete.
The below code sample has a reference to a library with an ExtensionMethods class which is defined in the External namespace. In the line marked with (*) comment, where the method is called using the static method call syntax, the compiler warns you that the type ExtensionMethods conflicts with an imported type. It also tells you that the method is obsolete (since you have shadowed the imported type, it sees your definition). So when you invoke the method, your code will run. In the line marked with (**) comment, where the method is called using the extension method call syntax, the compiler says that the call is ambiguous and the code won't compile. The only workaround I know of is to turn this call into line (*), which will produce the obsolete warning.
With this solution you will be able to call other extension methods from the referenced type if you use the extension method syntax, provided you don't have the same method defined in your class.
using System;
using External;
namespace Internal
{
class Program
{
static void Main(string[] args)
{
ExtensionMethods.IsNumeric(new object()); // (*)
new object().IsNumeric(); // (**)
}
}
}
namespace External
{
public static class ExtensionMethods
{
[Obsolete]
public static bool IsNumeric(this object o)
{
if (obj == null)
return false;
return obj.GetType().IsPrimitive || obj is double || (obj is Decimal || obj is DateTime) || obj is TimeSpan;
}
}
}

Object instantiation fails when using overloaded constructor

I recently stumbled upon an odd issue which I could not explain and I would be glad if someone could clarify why it happens.
The issue I've encountered is as follows:
I have an interface which is implemented, like so:
namespace InterfaceTwo
{
public interface IA { }
}
namespace InterfaceTwo
{
public class A : IA { }
}
And another interface which is implemented in a different project, like so:
namespace InterfaceOne
{
public interface IB { }
}
namespace InterfaceOne
{
public class B : IB { }
}
I have an object which uses those interfaces in it's constructors, like so:
using InterfaceOne;
using InterfaceTwo;
namespace MainObject
{
public class TheMainObject
{
public TheMainObject(IA iaObj) { }
public TheMainObject(IB iaObj) { }
}
}
And finally, I have a class which aggregates the above object, like so:
using InterfaceTwo;
using MainObject;
namespace ReferenceTest
{
public class ReferenceTest
{
public void DoSomething()
{
var a = new A();
var theMainObject = new TheMainObject(a);
}
}
}
Oddly, this code won't compile with the following error:
The type 'InterfaceOne.IB' is defined in an assembly that is not referenced.
You must add a reference to assembly 'InterfaceOne, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
c:\users\harry.baden\documents\visual studio 2013\Projects\ReferenceTest\ReferenceTest\ReferenceTest.cs 11 13 ReferenceTest
I also found that if I change one of the overloads to contain an extra parameter - it does compile... What got me thinking that the problem might be related to some sort of reflection issue which the compiler is running.
Thanks,
Barak.
namespace dependency issue. The error message pretty mush said it: your TheMainObject depends on InterfaceOne and must be properly referenced
this isn't directly related to constructor overloading...
Update:
It is more of a compiler behavior. To determine which overloaded method to use, the compiler has to
check all methods with the same name and same # of parameters to see if all the parameter types are referenced
then pick one method that matches the caller's parameter type (explicitly or implicitly).
We can verify step 1 and step 2 are separated with the following code:
using InterfaceOne;
using InterfaceTwo;
namespace MainObject
{
public class TheMainObject
{
public TheMainObject(IA obj) { }
public TheMainObject(IB obj, int x) { }
}
}
using InterfaceTwo;
using MainObject;
namespace ReferenceTest
{
public class ReferenceTest
{
public static void DoSomething()
{
var a = new A();
var theMainObject = new TheMainObject(a); //no error
}
}
}
The above code compiles because TheMainObject(IB obj, int x) is not a candidate for new TheMainObject(a). However if the constructor is defined as
public TheMainObject(IB obj) { }
or
public TheMainObject(IB obj, int x = 0) { }
a reference to InterfaceTwo.IB is required.
You can avoid this kind of reference check by calling the constructor at run-time, but this is error-prone and you should be cautious. For example:
public static void DoSomething()
{
var a = new A();
TheMainObject theMainObject = null;
var ctor = typeof (TheMainObject).GetConstructor(new[] {typeof (IA)});
if (ctor != null) {
theMainObject = (TheMainObject) ctor.Invoke(new object[] {a});
}
}
I did a little more research and found the following resources. Basically the type widening/narrowing step needs to know about all the types involved. (The VB version is just for reference because the C# spec is for VS.Net 2003).
Overload Resolution C#
Overload Resolution Visual Basic
See this for an explanation of a similar problem that I encountered. To quote the answer from the link:
The C# standard specifies that overload resolution (section 7.5.3) is performed by comparing each matching signature to determine which is a better fit. It doesn't say what happens when a reference is missing, so we must infer that it still needs to compare those unreferenced types.
In your example, it should be evident what overload you're using, but the compiler is not smart enough and will still try to compare both overloads, which is why both references are required.
Perhaps the easiest - but not the prettiest - solution (if you don't want to include the missing reference - which you may have a good reason not to) is to add an additional dummy parameter, effectively making it obvious to the compiler which overload you're calling; or transforming the two TheMainObject constructors into two methods with different names, e.g. TheMainObjectA(IA iaObj) and TheMainObjectB(IB ibObj) - i.e. avoiding overloading altogether.
Another possible solution is to use the dynamic keyword (for .NET 4.0 and above), although some people might discourage this as it can result in runtime errors if you're not careful:
public class TheMainObject
{
public TheMainObject(dynamic obj)
{
if (obj is IA)
{
// work with IA ...
}
else if (obj is IB)
{
// work with IB ...
}
else
{
// exception ...
}
}
}
This way, the compiler doesn't generate an error since the obj parameter is evaluated at runtime - your original code will work. If you choose to use this solution, also consider checking for RuntimeBinderException to avoid accidentally accessing invalid (non-existent) members of the dynamic type.

Is there a short and simple way for checking variable/property values?

I wonder whether there is a short and simple way for checking whether variable/property values match some condition?
Currently one of the most popular line in my code is similar to this one:
if (string.IsNullOrWhiteSpace(someFileName))
{
throw new NullReferenceException("'someFileName' must not be null.");
}
then the exception gets logged in the catch part and the execution continues and so on.
I don't like writing this line all over the place and just changing the variable name. It would be great if one could write something like this:
Assert.IsNotNullOrWhiteSpace(someFileName);
and it threw an exception saying that "{my variable} must not be null" with maybe some additional information like the parent class etc. that would help you to debug the code if you only have the logs available.
The problem with writing such a utility class that I encountered was that the thrown exception had of course the wrong stack trace like it happened in the utility method and not inside the method that called the assertion function.
This kind of value checking is required to especially work at runtime because I most of the time check user input like settings, paths, inputs etc.
EDIT:
I think I should have given an example of what I try to achieve:
public class FileExtractor {
public Form MainForm { get; set; }
public void ExtractFile(string fileName) {
Assert.IsNotNullOrWhiteSpace(fileName);
Assert.IsNotNull(MainForm);
// ...
}
}
and the let's call it Assert library should do this:
public static Assert {
public static void IsNotNullOrWhiteSpace(this string value) {
if (string.IsNullOrWhiteSpace(value)) {
// throw an exception like it occured in the ExtractFile
// the message should contain a hint like: "fileName must not be null"
}
}
public static void IsNotNull(this object value) {
if (value == null) {
// throw an excaption like it occured in the ExtractFile,
// the messagge should contain a hint like: "FileExtractor.MainForm must not be null."
}
}
EDIT-2
#CodeCaster - unfortunately I cannot not use C# 6 yet.
After some research and inspirated by two other questions here on stackoverflow
How to get Property Value from MemberExpression without .Compile()?
and
get name of a variable or parameter
I came up with this so far:
namespace ExceptionTest
{
class Program
{
static void Main(string[] args)
{
object test = null;
Assert.IsNotNull(() => test);
}
}
static class Assert
{
public static void IsNotNull<T>(Expression<Func<T>> expression)
{
MemberExpression memberExpr = expression.Body as MemberExpression;
var constExpr = memberExpr.Expression as ConstantExpression;
var value = (memberExpr.Member as FieldInfo).GetValue(constExpr.Value);
if (value == null)
{
throw new ArgumentNullException(memberExpr.Member.Name);
}
}
}
}
It almost does what I need. The last thing is to modify the stack trace so that it points to the Main method and not to the IsNotNull
You could use Debug Methods (http://msdn.microsoft.com/en-us/library/System.Diagnostics.Debug_methods%28v=vs.110%29.aspx), which however only work when compiling in debug mode.
Maybe Debug.WriteLineIf(Boolean, String) does what you need?
http://msdn.microsoft.com/en-us/library/y94y4370%28v=vs.110%29.aspx
How about applying attributes to the properties
http://msdn.microsoft.com/en-us/library/dd901590(VS.95).aspx
I think that you should try with Fody library library. For null-guards there is a package that you can find here. All libs are available via Nuget.
Fody is some kind AOP library that uses "weaving" technique to manipulate IL of an assembly and inject additional code.
So NullReferenceExcpetion (or maybe NullArgumentException) will be thrown exactly from your method.
Example from GitHub:
Your code
public void SomeMethod(string arg)
{
// throws ArgumentNullException if arg is null.
}
public void AnotherMethod([AllowNull] string arg)
{
// arg may be null here
}
What gets complied
public void SomeMethod(string arg)
{
if (arg == null)
{
throw new ArgumentNullException("arg");
}
}
public void AnotherMethod(string arg)
{
}

Categories

Resources