程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> .NET Custom Attribute Learning and Practice

.NET Custom Attribute Learning and Practice

編輯:.NET實例教程
This  week we prepare a team discussion on custom attribute of .Net,  here is some learning aggregation from my preparation, hope it will help for others.

Declarative programming vs imperative programming

·         A program is "declarative" if it describes what something is like, rather than how to create it.

·         Imperative programs explicitly specify an algorithm to achIEve a goal, while declarative programs explicitly specify the goal and leave the implementation of the algorithm to the support software

 

.Net metadata, in the Microsoft .Net framework, refers to certain data structures embedded within the Common Intermediate Language code that describes the high-level structure of the code. Metadata is the life blood of the .Net platform; Metadata describes all classes and class members that are defined in the assembly, and the classes and class members that the current assembly will call from another assembly. The metadata for a method contains the complete description of the method, including the class (and the assembly that contains the class), the return type and all of the method parameters.

A compiler for the common language runtime (CLR) will generate metadata during compilation and store the metadata (in a binary format) directly into assemblies and modules. Metadata in .NET cannot be underestimated. Metadata allows us to write a component in C# and let another application use the metadata from Visual Basic .NET. The metadata description of a type allows the runtime to layout an object in memory, to enforce security and type safety, and ensure version compatibilities. It makes the assemblIEs in .Net fully self-describing. This allows developers to share components across languages and eliminates the need for header files.

 

Reflection

Reflection is the ability to read metadata at runtime. Using reflection, it is possible to uncover the methods, propertIEs, and events of a type, and to invoke them dynamically. Reflection also allows us to create new types at runtime.

 

Custom attribute:

Attributes enhance flexibility in software systems because they promote loose coupling of functionality, custom attribute let users leverage the loose coupling power of attributes for their own purposes.

Developers can add metadata to their code through attributes. There are two types of attributes, custom and pseudo custom attributes.

A custom attribute is a regular class that inherits from the Attribute class. A custom attribute can be used on any method, property, class or entire assembly with the syntax: [Attribute name(optional parameter, optional name=value pairs)] as in:

 [Custom]

 [Custom(1)] [Custom(1), comment="yes"]

 

Custom attributes are interpreted by application code and not the CLR.When the compiler sees a custom attribute it will generate custom metadata that is not recognised by the CLR. The developer has to provide code to read the metadata and act on it.

 

    class CustomAttribute : Attribute

    {

        int ParamNumber = 0;

        string Comment = "";

 

        public CustomAttribute()

        {

        }

 

        public CustomAttribute(int num)

        {

            ParamNumber = num;

        }

 

        public String comment

        {

            set { Comment = value; }

        }

    }

The Visual C# compiler automatically adds the string "attribute" at the end of any attribute name. Consequently, every class implementing the handling of an attribute must end with this string but usage of this string is optional when using the attribute.

Using the attribute invokes the constructor of the class. Overloaded constructors are supported. Name-Value pairs are mapped to properties, the name denotes the name of the property and the value supplIEd is set by the property

 

Assemblies contain tables of metadata. These tables are described by the CIL specification. The metadata tables will have zero or more entrIEs and the position of an entry determines its index. When CIL code uses metadata it does so through a metadata token. This is a 32-bit value where the top 8 bits identify the appropriate metadata table, and the remaining 24 bits give the index of the metadata in the table, We can see metadata tables by ildasm: ildasm /metadata=RAW CustomAttributeTest.exe

 

Standard Attribute:

] lets you turn any public method of a WebService subclass into a method that you can expose as part of the Web service merely by attaching the [WebMethod] attribute to the method definition

        public class SomeWebService : System.Web.Services.WebService

        {

            [WebMethod]

            public DataSet GetDailySales()

            {

                return null;

                // code to process the request...

            }

        }

 

Custom Attributes vs. Class PropertIEs

An attribute takes the same "shape and form" as a property when you define it, but you can attach it to all manner of different assembly level types—not just Classes.  following table lists all the assembly level types that you can apply attributes to.

Assembly, Class, Delegate, Enum, Event, Interface, Method, Module, Parameter, Constructor, FIEld, Property, ReturnValue, Structure

Querying for our Custom Attribute

Once we have associated our attribute with various source code elements, we can query the metadata of these elements at run-time by using the .Net Framework Reflection classes. Reflection can be used to gain information about every ASPect of our class or assembly, including the class or assembly it.

First we need to extract the metadata for our class, which we do by using the typeof function :-

 

Type type = typeof(AttributeClass);

The custom attribute information is retrIEved into an object array by calling the Type.GetCustomAttributes() function. The method signatures for both overloaded versions are as follows:-

 

public object[] GetCustomAttributes(

                bool inherit                         //Search the members inheritance heirarchy

);

public object[] GetCustomAttributes(

                Type attributeType,        //Type of attribute to search for.

                bool inherit                         //Search the members inheritance heirarchy

We can now retrIEve the attribute information for our class, and loop through this array to obtain information about each attribute:-

 

object[] attributes = type.GetCustomAttributes(true);

foreach (object attribute in attributes) {

                Console.Write("  {0}", attribute.ToString());

                DescriptionAttribute da = attribute as DescriptionAttribute;

                if (da != null)

                                Console.WriteLine(".Description={0}", da.Description);

                else

                                Console.WriteLine();

}

 

below is an example for custom attribute, first, there are some example of system standard Attributes, and I also create one for testing, this attribute will serve as something like an almighty key, which give a backdoor to your application in development phase, and can be removed easily in release version.

 

Example:

using System;

using System.Collections.Generic;

using System.Text;

using System.Web.Services;

using System.Data;

using System.Diagnostics;

using System.Reflection;

 

 

namespace CustomAttributeTest

{

    [Custom(20080808, comment = "TOPSECRET")]

    class Program

    {

        static void Main(string[] args)

        {

            Old();Color c = Color.blue | Color.red;

            Console.WriteLine(c.ToString());

 

            SomeClass sc = new SomeClass();

            sc.UnitTest();

 

            System.Console.WriteLine("Enter your ID");

            string s = Console.ReadLine();

            int j = System.Int32.Parse(s);

            if (IsValid(j) == true)

            {

                Console.WriteLine("Valid user");

            }

            else

            {

                Console.WriteLine("Invalid user");

            }

            Console.ReadLine();

        }

 

        [Obsolete("Don''t use Old method, use New method", false)]

        static void Old()

        {

        }

        static void New()

        {

        }

 

        public static bool IsValid([Custom(-1)]int i)

        {

            Type type = typeof(Program);

            CustomAttribute CustAttr;

            //Querying Class Attributes

            foreach (Attribute attr in type.GetCustomAttributes(true))

            {

                CustAttr = attr as CustomAttribute;

                if (null != CustAttr)

                {

                    return CustAttr.comment == "TOPSECRET";

                }

            }

 

            //Querying Class-Method Attributes

            foreach (MethodInfo method in type.GetMethods())

            {

                foreach (Attribute attr in method.GetCustomAttributes(true))

                {

                    CustAttr = attr as CustomAttribute;

                    if (null != CustAttr)

                    {

                        return CustAttr.comment == "TOPSECRET";

                    }

                }

            }

 

 

            if (i > 100)

            {

                return true;

            }

            //Querying Class Attributes

            foreach (Attribute attr in type.GetCustomAttributes(true))

            {

                CustAttr = attr as CustomAttribute;

                if (null != CustAttr)

                {

                    return CustAttr.comment == "TOPSECRET";

                }            else

            {

                return false;

            }

        }

 

 

        public class SomeWebService : System.Web.Services.WebService

        {

            [WebMethod(Description = "Sales volume")]

            public DataSet GetDailySales()

            {

                return null;

                // code to process the request...

            }

        }

 

        public class SomeClass

        {

            [Conditional("DEBUG")]

            public void UnitTest()

            {

                // code to do unit testing...

            }

        }

 

        [Flags]

        enum Color

        {

            red = 0x001,

            blue = 0x002,

            green = 0x004,

        }

>    }

}

 

 

 

\\\\\\\\\\\\\\\\\\\\customattribute.cs\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;

using System.Diagnostics;

 

namespace CustomAttributeTest

{

    [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]

    public class CustomAttribute : Attribute

    {

        private int ParamNumber = 0;

        private string Comment = "";

        public virtual String comment

        {

            set { this.Comment = value; }

            get { return Comment; }

        }

 

        public CustomAttribute()

        {

        }

 

        public CustomAttribute(int num)

        {

            this.ParamNumber = num;

            this.Comment = "comment";

        }

    }

}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved