Использование .NET Reflection и Attribute для управления действием - PullRequest
0 голосов
/ 22 июня 2011

У меня этот код скопирован из C # 4.0 в двух словах, который использует API атрибутов / отражений для управления действием: количество выполненных тестов и сообщение об ошибке.

Когда я запускаю код, я получаю этот результат.

Method Method1 will be tested; reps=1; msg=; memo=
Test1
Method Method2 will be tested; reps=3; msg=; memo=abc
Test2
Test2
Test2
Method Method3 will be tested; reps=3; msg=Debugging Time!; memo=
Test3
Test3
Test3

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
  at Hello.Main () [0x00000] in <filename unknown>:0 

Почему это Unhandled Exception?

Исходный код выглядит следующим образом:

using System;
using System.Reflection;

[AttributeUsage (AttributeTargets.Method)]
public sealed class TestAttribute : Attribute
{
    public int Repititions;
    public string FailureMessage;
    public string Memo;

    public TestAttribute() : this(1) {}
    public TestAttribute(int repititions) {Repititions = repititions;}
}

class Foo
{
    [Test]
    public void Method1()
    {
        Console.WriteLine("Test1");
    }
    [Test(3, Memo="abc")]
    public void Method2()
    {
        Console.WriteLine("Test2");
    }
    [Test(3, FailureMessage="Debugging Time!")]
    public void Method3()
    {
        Console.WriteLine("Test3");
    }
}

class Hello
{
    static void Main()
    {
        foreach (MethodInfo mi in typeof(Foo).GetMethods())
        {
            TestAttribute att = (TestAttribute) Attribute.GetCustomAttribute(mi, typeof(TestAttribute)); 
            if (att != null)
                Console.WriteLine("Method {0} will be tested; reps={1}; msg={2}; memo={3}", mi.Name, att.Repititions, att.FailureMessage, att.Memo);
                for (int i = 0; i < att.Repititions; i++)
                    try
                    {
                        mi.Invoke(new Foo(), null);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception ("Error: " + att.FailureMessage, ex);
                    }
        }
    }
}

Ответы [ 4 ]

3 голосов
/ 22 июня 2011

Вам не хватает фигурных скобок {} в ваших if (att != null) и foreach.Одного отступа недостаточно.

class Hello
{
    static void Main()
    {
        foreach (MethodInfo mi in typeof(Foo).GetMethods())
        {
            TestAttribute att = (TestAttribute) Attribute.GetCustomAttribute(mi, typeof(TestAttribute)); 
            if (att != null)
            {
                Console.WriteLine("Method {0} will be tested; reps={1}; msg={2}; memo={3}", mi.Name, att.Repititions, att.FailureMessage, att.Memo);
                for (int i = 0; i < att.Repititions; i++)
                {
                    try
                    {
                        mi.Invoke(new Foo(), null);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception ("Error: " + att.FailureMessage, ex);
                    }
                }
            }
        }
    }
}
1 голос
/ 22 июня 2011

Поскольку MethodInfo mi - это ToString, унаследованный от объекта, который не имеет TestAttribute.Итак, теперь у вас есть значение att, равное нулю, и вы пытаетесь вызвать att.Repititions для него.Вы можете изменить его на

if (att != null)
{
    Console.WriteLine("Method {0} will be tested; reps={1}; msg={2}; memo={3}", mi.Name, att.Repititions,
                        att.FailureMessage, att.Memo);
    for (int i = 0; i < att.Repititions; i++)
        try
        {
            mi.Invoke(new Foo(), null);
        }
        catch (Exception ex)
        {
            throw new Exception("Error: " + att.FailureMessage, ex);
        }
}

, чтобы исправить это.

0 голосов
/ 22 июня 2011

Я добавил заглушку в ваш код - вы пытаетесь получить пользовательские атрибуты из метода ToString () System.String.

foreach (MethodInfo mi in typeof(Foo).GetMethods())
    {
        Console.WriteLine(mi.ToString());
        TestAttribute att = (TestAttribute) Attribute.GetCustomAttribute(mi, typeof(TestAttribute)); 
        if (att != null)
            Console.WriteLine("Method {0} will be tested; reps={1}; msg={2}; memo={3}", mi.Name, att.Repititions, att.FailureMessage, att.Memo);
            for (int i = 0; i < att.Repititions; i++)
                try
                {
                    mi.Invoke(new Foo(), null);
                }
                catch (Exception ex)
                {
                    throw new Exception ("Error: " + att.FailureMessage, ex);
                }
    }
0 голосов
/ 22 июня 2011

Вероятно, вы используете внутренний метод, который не имеет атрибута, поэтому эта строка завершается с ошибкой:

TestAttribute att = (TestAttribute) Attribute.GetCustomAttribute(mi, typeof(TestAttribute)); 

вы хотите использовать безопасное приведение:

TestAttribute att =  Attribute.GetCustomAttribute(mi, typeof(TestAttribute)) as TestAttribute; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...