是否可以使用属性本机检查参数的值?我已经看到像[FromUri]这样的系统属性。我希望有这样的事情:
public void Method([NotNull] string name, [NotNull] DateTime? date)
{ }
其中NotNull是一个检查值以查看它是否为null的属性。如果该值为null,则会引发错误。
以下是我目前的内容
我目前正在使用一个静态助手类,它接受一个表达式和参数本身来确定该值是否为null并使用该表达式来确定参数的名称。
// 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.";
}
}
奖金:如果我能以某种方式获取变量的名称而不传递带有名称的字符串,就像我当前的解决方案一样,这也很好。
答案 0 :(得分:3)
绝对不是最高效的,但你走在正确的轨道上。这是一个包装器,它可以完成PostSharp在IL中所做的一些工作。这仅适用于传递对象,它在将另一个方法作为参数传递时会发生故障。但是,解决这个问题只是一点点工作。
在生产中我会扩展它以构建一个委托的反射,我可以缓存以供以后使用。
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")));
}
}
答案 1 :(得分:2)
看看PostSharp(参见:http://www.postsharp.net)。它提供了许多属性,例如您正在寻找的属性。
PostSharp是一个预编译器,它将在代码中查找属性并生成适当的代码,如参数验证。