Reputation: 190889
I have this code copied from C# 4.0 in a nutshell that uses Attribute/Reflection API to control the action: the number of tests to run and show error message.
When I run the code, I got this result.
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
Why is this Unhandled Exception
?
The source code is as follows :
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);
}
}
}
}
Upvotes: 0
Views: 759
Reputation: 6103
I added a stub line to your code - you're trying to get custom attributes off of System.String's ToString() method.
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);
}
}
Upvotes: 0
Reputation: 27933
You were missing some curly braces {}
in your if (att != null)
and foreach
. Indentation alone is not enough.
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);
}
}
}
}
}
}
Upvotes: 3
Reputation: 68697
Because the MethodInfo mi
is the ToString
inherited from object which doesn't have a TestAttribute
. So now you have the value of att
is null and you try to call att.Repititions
on it. You can change it to
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);
}
}
to fix it.
Upvotes: 1
Reputation: 190952
You are likely hitting an internal method that does not have the attribute, hence this line fails:
TestAttribute att = (TestAttribute) Attribute.GetCustomAttribute(mi, typeof(TestAttribute));
you want to use the safe-cast:
TestAttribute att = Attribute.GetCustomAttribute(mi, typeof(TestAttribute)) as TestAttribute;
Upvotes: 0