Is it possible to check the value of a parameter natively using an attribute? I have seen some system attributes like [FromUri] used this way. I'm hoping for something like this:
public void Method([NotNull] string name, [NotNull] DateTime? date)
{ }
where NotNull is an attribute that checks the value to see if it is null. If the value is null it will throw an error.
Here is what I currently have
I'm currently using a static helper class that takes an expression and the parameter itself to determine whether the value is null and uses the expression to determine the name of the parameter.
// Invoke method within ArgumentHelper class
ArgumentHelper.RequireNotNullOrEmpty(() => state, state);
// Method within static class ArgumentHelper
public static void RequireNotNullOrEmpty<T>(this Expression<Func<T>> argumentExpression, string value)
{
var body = ((MemberExpression)argumentExpression.Body);
if (string.IsNullOrEmpty(value))
{
// Throw error "Required field '" + body.Member.Name + "' is missing.";
}
}
Bonus: It would also be nice if I could somehow get the name of the variable without passing a string with its name, just like my current solution.
Definitely not the most performant, but you're on the right track. Here's a wrapper that does a little of what PostSharp would be doing in IL. This is only good for passing objects, it breaks down as is when passing another method as a parameter. However, fixing that problem is just a little more work.
In production I would expand this to build the reflection into a delegate that I could cache for later use.
public class SomeClass
{
public void Method([NotNull] string Param1, [NotNull] string Param2)
{ }
}
public static class SomeClassExtensions
{
public static void InvokeWithNullCheck<TObject>(this TObject obj, Expression<Action<TObject>> expression)
{
var body = (MethodCallExpression)expression.Body;
foreach(var parameter in body.Method.GetParameters())
{
bool hasNotNullAttribute = parameter.CustomAttributes.Any(x => x.AttributeType.Equals(typeof(NotNullAttribute)));
if(hasNotNullAttribute && ((ConstantExpression)body.Arguments[parameter.Position]).Value == null)
{
throw new ArgumentException(String.Format("Mandatory parameter {0} was not supplied.", parameter.Name));
}
}
expression.Compile()(obj);
}
}
[TestFixture]
public class SomeClassTests
{
[Test]
public void Test()
{
var test = new SomeClass();
Assert.Throws<ArgumentException>(() => test.InvokeWithNullCheck(x => x.Method(null, "Test")));
}
}
Take a look at PostSharp (see: http://www.postsharp.net). It provides a lot of attributes like that one you are looking for.
PostSharp is a precompiler which will lookup the attributes in your code and generate appropriate code like parameter validation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With