C# 使用属性检查空参数

C# 使用属性检查空参数,c#,C#,是否可以使用属性本机检查参数的值?我见过一些系统属性,比如[FromUri]是这样使用的。我希望这样: public void Method([NotNull] string name, [NotNull] DateTime? date) { } 其中NotNull是一个属性,用于检查值是否为null。如果该值为null,则会抛出错误 这是我目前拥有的 我目前正在使用一个静态帮助器类,它接受一个表达式和参数本身来确定值是否为null,并使用表达式来确定参数的名称 // Invoke meth

是否可以使用属性本机检查参数的值?我见过一些系统属性,比如[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.";
        }
    }
//在ArgumentHelper类中调用方法
ArgumentHelper.requireNotNullEmpty(()=>状态,状态);
//静态类ArgumentHelper中的方法
public static void requirentnullorempty(此表达式参数表达式,字符串值)
{
var body=((MemberExpression)argumentExpression.body);
if(string.IsNullOrEmpty(value))
{
//抛出错误“必填字段”“+body.Member.Name+””;
}
}
奖金:如果我能够以某种方式获得变量的名称,而无需像我当前的解决方案那样传递带有名称的字符串,那也会很好。

看看PostSharp(请参阅:)。它提供了许多与您正在寻找的属性类似的属性


PostSharp是一个预编译器,它将查找代码中的属性并生成适当的代码,如参数验证。

当然不是最有效的,但您的方法是正确的。这里有一个包装器,它做了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")));
    }
}
公共类SomeClass
{
公共无效方法([NotNull]字符串参数1,[NotNull]字符串参数2)
{ }
}
公共静态类扩展
{
公共静态void InvokeWithNullCheck(这个TObject对象,表达式)
{
var body=(MethodCallExpression)expression.body;
foreach(body.Method.GetParameters()中的var参数)
{
bool hasNotNullAttribute=parameter.CustomAttributes.Any(x=>x.AttributeType.Equals(typeof(NotNullAttribute));
if(hasNotNullAttribute&((ConstantExpression)body.Arguments[parameter.Position])。Value==null)
{
抛出新的ArgumentException(String.Format(“未提供必需参数{0}.”,parameter.Name));
}
}
expression.Compile()(obj);
}
}
[测试夹具]
公共类测试
{
[测试]
公开无效测试()
{
var test=newsomeclass();
Assert.Throws(()=>test.InvokeWithNullCheck(x=>x.Method(null,“test”));
}
}

与简单的
==null
相比,您的静态助手类的处理成本似乎要高得多。是否可以使用属性本机检查参数的值?这不是属性的真正用途。属性用于用元数据装饰类、方法、属性和参数,而不是实际处理本身。您仍然需要调用方或函数来实际检查null,在这种情况下,只检查null会更容易。您不会得到自动运行时检查。
[FromUri]
属性的工作方式仅限于调用方(即web api本身)检查其试图调用的方法的属性,如果它看到该属性,则知道从uri插入值。属性本身不会这样做。这是来电者的责任。@MattBurland谢谢您的回复。您提到的属性更多地用于元数据而不是处理。我知道对于属性,我有一个
[Required]
标记,确保属性不为null,如果为null,则抛出错误。这不是和我正在寻找的相似吗,或者我误解了它实际上在做什么吗?顺便说一句,我并不是想自相矛盾,我只是想真正理解这些东西。我还在学习。:)@BradGermain:是和否。
[Required]
标记根本不起任何作用,除非使用这些属性的代码实际检查它。它用于验证,验证代码将在模型中的所有属性中运行,并检查它们是否具有
[必需]
属性,如果有,则检查是否为null。实际检查仍然是调用代码的责任。它本身没有任何作用。感谢您发布@MartinMulder。我听说PostSharp是一种可能的解决方案,但我想知道是否有必要在不安装任何附加软件的情况下以本机方式进行。我仅限于visual studio 2013中默认安装的内容。因此。。。企业库不是选项?PostSharp是企业库的一部分吗?如果是,它引入了什么版本,因为我们有企业库4。好的,我来看看。谢谢您能否解释(或提供链接)如何“将反射构建到委托中”?