Friday, July 14, 2023

How to create attributes and Apply attributes in .NET


Steps to create a custom attribute class

  • Create a public class which derives from System.Attribute class. The name of class should suffix with Attribute word but it is not mandatory.
  • Apply the AttributeUsage attribute on this custom attribute class so that scope of the custom class on the target class is defined. The target class is the class which uses the custom attribute class.
  • To define the custom attribute class, you can use fields, properties and constructors in it like any other class.
  • To apply this custom attribute class in target class, create an instance of the custom attribute class in target class. 
  • For this, use Attribute.GetCustomAttribute method in the target class. There are many overloaded version of this method. It will return an instance of the custom attribute class. Check that the instance is not null. If it is not null, get all its properties and methods using dot operator.

EXAMPLE1: Create a custom attribute class which is used to display all the methods of a target class, when the attribute is applied on the target class.

STEP1. Create custom attribute class named as DisplayMethodsAttribute 

using System;
using System.Reflection;

namespace ConsoleApp1.AttributeDemo2
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    public class DisplayMethodsAttribute : System.Attribute
    {
        public void DisplayMethods(Type classType)
        {
            MethodInfo[] methods = classType.GetMethods();
            for (int i = 0; i < methods.Length; i++)
            {
                Console.WriteLine($"method {i+1} is {methods[i].Name} in {classType.Name}");
            }
        }
    }
}
 

STEP2. Create target class named as Test. You can create n number of target classes.


using System;

namespace ConsoleApp1.AttributeDemo2
{
    [DisplayMethods()] // to list all the methods of this class in console
    public  class Test
    {
        public void Display()
        {
            Console.WriteLine("Test method1: Display");
        }

        public void Show()
        {
            Console.WriteLine("Test method2: Show");
        }

        public static void Run()
        {
            DisplayMethodsAttribute attr = (DisplayMethodsAttribute)Attribute.GetCustomAttribute(typeof(Test), typeof(DisplayMethodsAttribute));

            if (attr == null)
            {
                Console.WriteLine("DisplayMethodsAttribute is NULL");
            }
            else
            {
                //Console.WriteLine(attr.Company + " is located at " + attr.Location);
                attr.DisplayMethods(typeof(Test));
            }
        }
    }
}

STEP3. Run the application by using target class in any other client class.


using ConsoleApp1.AttributeDemo2;

namespace ConsoleApp1
{

    public class Program
    {
        public static void Main()
        {
            Test.Run();
        }
    }
}
 

EXAMPLE2: Example of Application of Attribute in ASP.NET Core Application

Create web project using ASP.NET Core Web App (Model-View-Controller) template.

STEP1. Create a custom attribute class as given below.


using System;

namespace WebApplicationRP
{
    // this attribute initializes the property IsOddHour as per condition
    // when this class is initialized in target method
    // We apply this attribute on a method
    [AttributeUsage(AttributeTargets.Method, Inherited =false, AllowMultiple =false)]
    public class OddHoursAttribute : Attribute
    {
        public bool IsOddHour { get; set; }
        public OddHoursAttribute()
        {
                int hour = DateTime.Now.Hour;
                IsOddHour = hour > 20 && hour < 24 ;
        }
    }
}

STEP2. Apply the custom attribute on action method of HomeController


using Microsoft.AspNetCore.Mvc;

namespace WebApplicationRP.Controllers
{
    public class HomeController : Controller
    {
        [OddHours]
        public IActionResult Index()
        {
            return View();
        }
    }
}

STEP3. In Startup class, expose the metadata of the custom class attribute in the middleware inserted between enable routing and use endpoints. In odd hours, the custom attribute on action method redirects to google server home page.


using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace WebApplicationRP
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            
            app.UseRouting();
            
            // middleware inserted between routing and endpoints
            app.Use(async (context, next) =>
            {
                var endpoint = context.GetEndpoint();
                if (endpoint != null)
                {
                    var oddhour = endpoint.Metadata.GetMetadata<OddHoursAttribute>();
                    if (oddhour != null && oddhour.IsOddHour)
                    {
                        //context.Response.WriteAsync("This is odd hour for this endpoint");
                        // URL must be valid. www.google.com not work
                        context.Response.Redirect("https://www.google.com");
                    }
                }
                await next();
            });

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute
                (
                name: "Defaults",
                pattern: "/{controller}/{action}/{id?}",
                defaults: new { controller = "Home", action = "Index" }
                );

            });
        }
    }
}

STEP4. Index View is displayed in not odd hours.


<h1>The current time @DateTime.Now.ToLongTimeString()</h1>

Updated on 13 July 2023

No comments:

Post a Comment

Hot Topics