CSharp Advanced L05-Attributes+Reflection
-
Upload
mohammad-shaker -
Category
Software
-
view
233 -
download
0
description
Transcript of CSharp Advanced L05-Attributes+Reflection
Mohammad Shaker
mohammadshaker.com
@ZGTRShaker
2011, 2012, 2013, 2014
C# AdvancedL05-Attributes, Conditional Methods and
Reflection
Attributes
AttributesMuch of the C# language enables the programmer to specify declarative information about the entities defined
in the program. For example, the accessibility of a method in a class is specified by decorating it with the method-modifiers public, protected, internal, and private. C# enables programmers to invent new kinds of declarative information, called attributes. Programmers can then attach attributes to various program
entities, and retrieve attribute information in a run-time environment. For instance, a framework might define a HelpAttribute attribute that can be placed on certain program elements (such as classes and methods) to
provide a mapping from those program elements to their documentation. (from MSDN)
"DLL Hell“ problem
"DLL Hell“ problem
• can be caused by one application overwriting a shared library of another
application, usually with a different version.
• Imagine you write an application with a shared library and then years later create
a new application with an updated library.
• In order not to break old programs, what do you do with the new library? You
give it a different name, store it in a different location, or overwrite the old ones?
"DLL Hell“ problem
• can be caused by one application overwriting a shared library of another
application, usually with a different version.
• Imagine you write an application with a shared library and then years later create
a new application with an updated library.
• In order not to break old programs, what do you do with the new library? You
give it a different name, store it in a different location, or overwrite the old ones?
Assemblies
Assemblies
• What’s an assembly?
– An assembly is a file that is automatically generated by the compiler upon successful
compilation of every.NET application. It can be either a Dynamic Link Library or an executable
file. It is generated only once for an application and upon each subsequent compilation the
assembly gets updated.
– contains the intermediate code, resources, and the metadata for itself.
– We can have a look inside the assembly using the ildasm (Intermediate Language
Disassembler) tool that comes as part of Visual Studio.
– To access it you need to open the Visual Studio Command Prompt and type ildasm.exe. This
will launch a Windows application that you can use to explore any.Net application.
Attributes and Reflection
• Attributes
– Attributes provide a powerful method of associating declarative information with C# code
(types, methods, properties, and so forth).
– Once associated with a program entity, the attribute can be queried at run time and used in
any number of ways.
Attributes and Reflection
• Example usage of attributes includes:
– Associating help documentation with program entities (through a Help attribute).
– Associating value editors to a specific type in a GUI framework (through
a ValueEditor attribute).
Example at the start!
Example at the start!If you understand this, it’s over
Example at the start
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Example at the start
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Attributes
Example at the start
public static class EnumExtensions{
public static string Description(this Enum enumValue){
var enumType = enumValue.GetType();var field = enumType.GetField(enumValue.ToString());var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);return ((DescriptionAttribute)attributes[0]).Description;
}}
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Example at the start
public static class EnumExtensions{
public static string Description(this Enum enumValue){
var enumType = enumValue.GetType();var field = enumType.GetField(enumValue.ToString());var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);return ((DescriptionAttribute)attributes[0]).Description;
}}
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Extension Method
Example at the start
public static class EnumExtensions{
public static string Description(this Enum enumValue){
var enumType = enumValue.GetType();var field = enumType.GetField(enumValue.ToString());var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);return ((DescriptionAttribute)attributes[0]).Description;
}}
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Reflection
Example at the start
public static class EnumExtensions{
public static string Description(this Enum enumValue){
var enumType = enumValue.GetType();var field = enumType.GetField(enumValue.ToString());var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);return ((DescriptionAttribute)attributes[0]).Description;
}}
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Example at the start
public static class EnumExtensions{
public static string Description(this Enum enumValue){
var enumType = enumValue.GetType();var field = enumType.GetField(enumValue.ToString());var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);return ((DescriptionAttribute)attributes[0]).Description;
}}
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Example at the start
public static class EnumExtensions{
public static string Description(this Enum enumValue){
var enumType = enumValue.GetType();var field = enumType.GetField(enumValue.ToString());var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);return ((DescriptionAttribute)attributes[0]).Description;
}}
for (CarColour cc = CarColour.White; cc <= CarColour.Red; cc++){
Console.WriteLine(cc.Description());}
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Example at the start
public static class EnumExtensions{
public static string Description(this Enum enumValue){
var enumType = enumValue.GetType();var field = enumType.GetField(enumValue.ToString());var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);return ((DescriptionAttribute)attributes[0]).Description;
}}
for (CarColour cc = CarColour.White; cc <= CarColour.Red; cc++){
Console.WriteLine(cc.Description());}
enum CarColour
{
[Description("Ice Cream White")]
White,
[Description("Carbon Black")]
Black,
[Description("Sterling Silver")]
Silver,
Red
}
Ice Cream WhiteCarbon BlackSterling SilverRed
Concept of Attributes
Attributes Basics
• Attributes are generally applied physically in front of type and type member
declarations. They're declared with square brackets, "[" and "]", surrounding the
attribute such as the followingObsoleteAttribute attribute:
• [ObsoleteAttribute]
AttributeUsage Describes how a custom attribute class can be used.
Conditional Marks a conditional method, a method whose execution depends on a specified preprocessing identifier.
Obsolete Marks a program entity that should not be used.
Attribute, Obsolete
Pre-Defined Attributes using System;
class BasicAttributeDemo{
[Obsolete]public void MyFirstdeprecatedMethod(){
Console.WriteLine("Called MyFirstdeprecatedMethod().");}
[ObsoleteAttribute]public void MySecondDeprecatedMethod(){
Console.WriteLine("Called MySecondDeprecatedMethod().");}
[Obsolete("You shouldn't use this method anymore.")]public void MyThirdDeprecatedMethod(){
Console.WriteLine("Called MyThirdDeprecatedMethod().");}
Pre-Defined Attributes using System;
class BasicAttributeDemo{
[Obsolete]public void MyFirstdeprecatedMethod(){
Console.WriteLine("Called MyFirstdeprecatedMethod().");}
[ObsoleteAttribute]public void MySecondDeprecatedMethod(){
Console.WriteLine("Called MySecondDeprecatedMethod().");}
[Obsolete("You shouldn't use this method anymore.")]public void MyThirdDeprecatedMethod(){
Console.WriteLine("Called MyThirdDeprecatedMethod().");}
Pre-Defined Attributes using System;
class BasicAttributeDemo{
[Obsolete]public void MyFirstdeprecatedMethod(){
Console.WriteLine("Called MyFirstdeprecatedMethod().");}
[ObsoleteAttribute]public void MySecondDeprecatedMethod(){
Console.WriteLine("Called MySecondDeprecatedMethod().");}
[Obsolete("You shouldn't use this method anymore.")]public void MyThirdDeprecatedMethod(){
Console.WriteLine("Called MyThirdDeprecatedMethod().");}
Pre-Defined Attributes using System;
class BasicAttributeDemo{
[Obsolete]public void MyFirstdeprecatedMethod(){
Console.WriteLine("Called MyFirstdeprecatedMethod().");}
[ObsoleteAttribute]public void MySecondDeprecatedMethod(){
Console.WriteLine("Called MySecondDeprecatedMethod().");}
[Obsolete("You shouldn't use this method anymore.")]public void MyThirdDeprecatedMethod(){
Console.WriteLine("Called MyThirdDeprecatedMethod().");}
Pre-Defined Attributes // make the program thread safe for COM[STAThread]static void Main(string[] args){
BasicAttributeDemo attrDemo = new BasicAttributeDemo();
attrDemo.MyFirstdeprecatedMethod();attrDemo.MySecondDeprecatedMethod();attrDemo.MyThirdDeprecatedMethod();
}}
Pre-Defined Attributes // make the program thread safe for COM[STAThread]static void Main(string[] args){
BasicAttributeDemo attrDemo = new BasicAttributeDemo();
attrDemo.MyFirstdeprecatedMethod();attrDemo.MySecondDeprecatedMethod();attrDemo.MyThirdDeprecatedMethod();
}}
Attribute, AttributeUsage
AttributeUsageDescribes how a custom attribute class can be used.
[AttributeUsage(validon,AllowMultiple=allowmultiple,Inherited=inherited
)]
User-Defined Attributes
[Author("H. Ackerman", version = 1.1)] class SampleClass
User-Defined Attributes
[Author("H. Ackerman", version = 1.1)] class SampleClass
Author anonymousAuthorObject = new Author("H. Ackerman"); anonymousAuthorObject.version = 1.1;
User-Defined Attributes
[Author("H. Ackerman", version = 1.1)] class SampleClass
Author anonymousAuthorObject = new Author("H. Ackerman"); anonymousAuthorObject.version = 1.1;
conceptually equivalent
Attribute, Conditional
Conditional Methodsallow developers to create methods whose calls can be placed in the code and then either
included or omitted during compilation based on a preprocessing symbol.
Conditional Methods
• The Conditional attribute takes one parameter — the preprocessing
identifier that controls whether the method call is included when clients are
compiled. If the preprocessing identifier is defined, the method is called;
otherwise, the call is never inserted in the client's code.
using System; using System.Diagnostics;namespace TraceFunctions{
public class Trace {
[Conditional("DEBUG")] public static void Message(string traceMessage) {
Console.WriteLine("[TRACE] - " + traceMessage); }
} }
[Serializable]
[Serializable]Says that the object is Serializable
[Serializable]Says that the object is Serializable
So you can Stream it and save the object into, like, a file!
Reflection
ReflectionAsk the object itself about itself
Types
Types and Reflection
• Reflection
– Provides objects (of type Type) that encapsulate assemblies, modules and types.
– You can use reflection to dynamically create an instance of a type, bind the type to an existing
object, or get the type from an existing object and invoke its methods or access its fields and
properties.
– If you are using attributes in your code, Reflection enables you to access them.
Types and Reflection
• Reflection is useful in the following situations:
– When you need to access attributes in your program's metadata.
• “Accessing Attributes With Reflection”
– For examining and instantiating types in an assembly.
– For building new types at runtime. Use classes in System.Reflection.Emit
– For performing late binding, accessing methods on types created at run time.
Types and Reflection
• Reflection is useful in the following situations:
– When you need to access attributes in your program's metadata.
• “Accessing Attributes With Reflection”
– For examining and instantiating types in an assembly.
– For building new types at runtime. Use classes in System.Reflection.Emit
– For performing late binding, accessing methods on types created at run time.
System.Type class
System.Type class
• The System.Type class is central to reflection.
• The common language runtime creates the Type for a loaded type when
reflection requests it. You can use a Type object's methods, fields, properties, and
nested classes to find out everything about that type.
System.Type class
• Simple example of Reflection using the static method GetType - inherited by all
types from the Object base class - to obtain the type of a variable:
// Using GetType to obtain type information:int i = 42;System.Type type = i.GetType();System.Console.WriteLine(type);
System.Type class
• Simple example of Reflection using the static method GetType - inherited by all
types from the Object base class - to obtain the type of a variable:
// Using GetType to obtain type information:int i = 42;System.Type type = i.GetType();System.Console.WriteLine(type);
System.Int32
Types and Reflection
• Identifying all Types that Implement an Interface (http://www.blackwasp.co.uk/)public interface IParent { }public class Parent { }public class Child1 : Parent { }public class Child2 : Parent { }public class Grandchild11 : Child1 { }public class Grandchild12 : Child1 { }public class Grandchild21 : Child2 { }public class Grandchild22 : Child2 { }public class NotAChild { }public class NotAGrandchild : NotAChild { }
Type parentType = typeof(IParent);Assembly assembly = Assembly.GetExecutingAssembly();Type[] types = assembly.GetTypes();
Types and Reflection
• Identifying all Types that Implement an Interfacepublic interface IParent { }public class Parent { }public class Child1 : Parent { }public class Child2 : Parent { }public class Grandchild11 : Child1 { }public class Grandchild12 : Child1 { }public class Grandchild21 : Child2 { }public class Grandchild22 : Child2 { }public class NotAChild { }public class NotAGrandchild : NotAChild { }
IEnumerable<Type> imp = types.Where(t => t.GetInterfaces().Contains(interfaceType));
foreach (Type type in imp){
Console.WriteLine(type.Name);}
/* OUTPUT ParentChild1Child2Grandchild11Grandchild12Grandchild21Grandchild22 */
Type parentType = typeof(IParent);Assembly assembly = Assembly.GetExecutingAssembly();Type[] types = assembly.GetTypes();
Types and Reflection
• Identifying all Subclasses of a Class (http://www.blackwasp.co.uk/)public interface IParent { }public class Parent { }public class Child1 : Parent { }public class Child2 : Parent { }public class Grandchild11 : Child1 { }public class Grandchild12 : Child1 { }public class Grandchild21 : Child2 { }public class Grandchild22 : Child2 { }public class NotAChild { }public class NotAGrandchild : NotAChild { }
Type parentType = typeof(IParent);Assembly assembly = Assembly.GetExecutingAssembly();Type[] types = assembly.GetTypes();
Types and Reflection
• Identifying all Subclasses of a Classpublic interface IParent { }public class Parent { }public class Child1 : Parent { }public class Child2 : Parent { }public class Grandchild11 : Child1 { }public class Grandchild12 : Child1 { }public class Grandchild21 : Child2 { }public class Grandchild22 : Child2 { }public class NotAChild { }public class NotAGrandchild : NotAChild { }
IEnumerable<Type> subclasses = types.Where(t => t.IsSubclassOf(parentType));
foreach (Type type in subclasses){
Console.WriteLine(type.Name);}
/* OUTPUT Child1Child2Grandchild11Grandchild12Grandchild21Grandchild22 */
Type parentType = typeof(IParent);Assembly assembly = Assembly.GetExecutingAssembly();Type[] types = assembly.GetTypes();
Test CaseGetting Constructors of String Class
Types and Reflection// This program lists all the public constructors // of the System.String class.using System;using System.Reflection;class ListMembers{
public static void Main(String[] args){
Type t = typeof(System.String);Console.WriteLine("Listing all the public constructors of the {0} type", t);// Constructors.ConstructorInfo[] ci = t.GetConstructors(BindingFlags.Public | BindingFlags.Instance);Console.WriteLine("//Constructors");PrintMembers(ci);
}public static void PrintMembers(MemberInfo[] ms){
foreach (MemberInfo m in ms){
Console.WriteLine("{0}{1}", " ", m);}Console.WriteLine();
}}
Types and Reflection// This program lists all the public constructors // of the System.String class.using System;using System.Reflection;class ListMembers{
public static void Main(String[] args){
Type t = typeof(System.String);Console.WriteLine("Listing all the public constructors of the {0} type", t);// Constructors.ConstructorInfo[] ci = t.GetConstructors(BindingFlags.Public | BindingFlags.Instance);Console.WriteLine("//Constructors");PrintMembers(ci);
}public static void PrintMembers(MemberInfo[] ms){
foreach (MemberInfo m in ms){
Console.WriteLine("{0}{1}", " ", m);}Console.WriteLine();
}}
Listing all the public constructors of the System.String type//Constructors
Void.ctor(Char*)Void.ctor(Char*, Int32, Int32)Void.ctor(SByte*)Void.ctor(SByte*, Int32, Int32)Void.ctor(SByte*, Int32, Int32, System.Text.Encoding)Void.ctor(Char[], Int32, Int32)Void.ctor(Char[])Void.ctor(Char, Int32)
Press any key to continue...
Invoking Overloaded Methods Using Reflectionhttp://www.blackwasp.co.uk/
Invoking Overloaded Methods Using Reflectionpublic class Test{
public void ShowMessage(){
Console.WriteLine("Hello, world");}
public void ShowMessage(string msg, int timesToShow){
for (int i = 0; i < timesToShow; i++){
Console.WriteLine(msg);}
}}
Invoking Overloaded Methods Using Reflectionpublic class Test{
public void ShowMessage(){
Console.WriteLine("Hello, world");}
public void ShowMessage(string msg, int timesToShow){
for (int i = 0; i < timesToShow; i++){
Console.WriteLine(msg);}
}}
Test test = new Test();Type type = test.GetType();MethodInfo method = type.GetMethod("ShowMessage", new Type[] { typeof(string), typeof(int) });method.Invoke(test, new object[] { "Exterminate!", 3 });
Invoking Overloaded Methods Using Reflectionpublic class Test{
public void ShowMessage(){
Console.WriteLine("Hello, world");}
public void ShowMessage(string msg, int timesToShow){
for (int i = 0; i < timesToShow; i++){
Console.WriteLine(msg);}
}}
Test test = new Test();Type type = test.GetType();MethodInfo method = type.GetMethod("ShowMessage", new Type[] { typeof(string), typeof(int) });method.Invoke(test, new object[] { "Exterminate!", 3 });
Invoking Overloaded Methods Using Reflectionpublic class Test{
public void ShowMessage(){
Console.WriteLine("Hello, world");}
public void ShowMessage(string msg, int timesToShow){
for (int i = 0; i < timesToShow; i++){
Console.WriteLine(msg);}
}}
Test test = new Test();Type type = test.GetType();MethodInfo method = type.GetMethod("ShowMessage", new Type[] { typeof(string), typeof(int) });method.Invoke(test, new object[] { "Exterminate!", 3 });
Exterminate!Exterminate!Exterminate!
Accessing Attributes Through Reflection
Accessing Attributes Through ReflectionYou don’t have to read..
Accessing Attributes Through Reflection
class MainClass{
public static void Main(){
System.Reflection.MemberInfo info = typeof(MyClass);object[] attributes = info.GetCustomAttributes(true);for (int i = 0; i < attributes.Length; i++){
System.Console.WriteLine(attributes[i]);}
}}
Accessing Attributes Through Reflection
class MainClass{
public static void Main(){
System.Reflection.MemberInfo info = typeof(MyClass);object[] attributes = info.GetCustomAttributes(true);for (int i = 0; i < attributes.Length; i++){
System.Console.WriteLine(attributes[i]);}
}}
Accessing Attributes Through Reflection
• Let’s have the following giant example!
public class IsTestedAttribute : Attribute{
public override string ToString(){
return "Is Tested";}
}
Concept of Attributes[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]public class AuthorAttribute : Attribute{
public AuthorAttribute(string name){
this.name = name;this.version = 0;
}public string Name{ get
{return name;
}}public int Version{
get{
return version;}set{
version = value;}
}public override string ToString(){
string value = "Author : " + Name;if (version!= 0){
value += " Version : " + Version.ToString();}return value;
}private string name;private int version;
}
Concept of Attributes[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]public class AuthorAttribute : Attribute{
public AuthorAttribute(string name){
this.name = name;this.version = 0;
}public string Name{ get
{return name;
}}public int Version{
get{
return version;}set{
version = value;}
}public override string ToString(){
string value = "Author : " + Name;if (version!= 0){
value += " Version : " + Version.ToString();}return value;
}private string name;private int version;
}
Concept of Attributes[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]public class AuthorAttribute : Attribute{
public AuthorAttribute(string name){
this.name = name;this.version = 0;
}public string Name{ get
{return name;
}}public int Version{
get{
return version;}set{
version = value;}
}public override string ToString(){
string value = "Author : " + Name;if (version!= 0){
value += " Version : " + Version.ToString();}return value;
}private string name;private int version;
}
Concept of Attributes[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]public class AuthorAttribute : Attribute{
public AuthorAttribute(string name){
this.name = name;this.version = 0;
}public string Name{ get
{return name;
}}public int Version{
get{
return version;}set{
version = value;}
}public override string ToString(){
string value = "Author : " + Name;if (version!= 0){
value += " Version : " + Version.ToString();}return value;
}private string name;private int version;
}
Accessing Attributes Through Reflection
[Author("Joe Programmer")]class Account{
// Attach the IsTestedAttribute custom attribute to this method.[IsTested]public void AddOrder(Order orderToAdd){
orders.Add(orderToAdd);}
private ArrayList orders = new ArrayList();}
[Author("Jane Programmer", Version = 2), IsTested()]class Order{
// add stuff here...}
Accessing Attributes Through Reflection
[Author("Joe Programmer")]class Account{
// Attach the IsTestedAttribute custom attribute to this method.[IsTested]public void AddOrder(Order orderToAdd){
orders.Add(orderToAdd);}
private ArrayList orders = new ArrayList();}
[Author("Jane Programmer", Version = 2), IsTested()]class Order{
// add stuff here...}
Accessing Attributes Through Reflection
[Author("Joe Programmer")]class Account{
// Attach the IsTestedAttribute custom attribute to this method.[IsTested]public void AddOrder(Order orderToAdd){
orders.Add(orderToAdd);}
private ArrayList orders = new ArrayList();}
[Author("Jane Programmer", Version = 2), IsTested()]class Order{
// add stuff here...}
Accessing Attributes Through Reflectionclass MainClass{
private static bool IsMemberTested(MemberInfo member){
foreach (object attribute in member.GetCustomAttributes(true)){
if (attribute is IsTestedAttribute){
return true;}
}return false;
}
private static void DumpAttributes(MemberInfo member){
Console.WriteLine("Attributes for : " + member.Name);foreach (object attribute in member.GetCustomAttributes(true)){
Console.WriteLine(attribute);}
}
Concept of Attributespublic static void main(){ DumpAttributes(typeof(Account));
foreach (MethodInfo method in (typeof(Account)).GetMethods()){
if (IsMemberTested(method)){
Console.WriteLine("Member {0} is tested!", method.Name);}else{
Console.WriteLine("Member {0} is NOT tested!", method.Name);}
}Console.WriteLine();
// display attributes for Order classDumpAttributes(typeof(Order));
// display attributes for methods on the Order classforeach (MethodInfo method in (typeof(Order)).GetMethods()){
if (IsMemberTested(method)){
Console.WriteLine("Member {0} is tested!", method.Name);}else{
Console.WriteLine("Member {0} is NOT tested!", method.Name);}
}Console.WriteLine(); } }
Concept of Attributespublic static void main(){ DumpAttributes(typeof(Account));
foreach (MethodInfo method in (typeof(Account)).GetMethods()){
if (IsMemberTested(method)){
Console.WriteLine("Member {0} is tested!", method.Name);}else{
Console.WriteLine("Member {0} is NOT tested!", method.Name);}
}Console.WriteLine();
// display attributes for Order classDumpAttributes(typeof(Order));
// display attributes for methods on the Order classforeach (MethodInfo method in (typeof(Order)).GetMethods()){
if (IsMemberTested(method)){
Console.WriteLine("Member {0} is tested!", method.Name);}else{
Console.WriteLine("Member {0} is NOT tested!", method.Name);}
}Console.WriteLine(); } }
Concept of Attributespublic static void main(){ DumpAttributes(typeof(Account));
foreach (MethodInfo method in (typeof(Account)).GetMethods()){
if (IsMemberTested(method)){
Console.WriteLine("Member {0} is tested!", method.Name);}else{
Console.WriteLine("Member {0} is NOT tested!", method.Name);}
}Console.WriteLine();
// display attributes for Order classDumpAttributes(typeof(Order));
// display attributes for methods on the Order classforeach (MethodInfo method in (typeof(Order)).GetMethods()){
if (IsMemberTested(method)){
Console.WriteLine("Member {0} is tested!", method.Name);}else{
Console.WriteLine("Member {0} is NOT tested!", method.Name);}
}Console.WriteLine(); } }
Accessing Attributes Through Reflection
Attributes for : AccountAuthor : Joe ProgrammerMember AddOrder is tested!Member ToString is NOT tested!Member Equals is NOT tested!Member GetHashCode is NOT tested!Member GetType is NOT tested!
Attributes for : OrderAuthor : Jane Programmer Version : 2Is TestedMember ToString is NOT tested!Member Equals is NOT tested!Member GetHashCode is NOT tested!Member GetType is NOT tested!
Press any key to continue...
http://www.mohammadshaker.com
https://twitter.com/ZGTRShaker @ZGTRShaker
https://de.linkedin.com/pub/mohammad-shaker/30/122/128/
http://www.slideshare.net/ZGTRZGTR
https://www.goodreads.com/user/show/11193121-mohammad-shaker
https://plus.google.com/u/0/+MohammadShaker/
https://www.youtube.com/channel/UCvJUfadMoEaZNWdagdMyCRA
http://mohammadshakergtr.wordpress.com/