Custom attribute enables the capability of creating user defined attributes (types) extending “Attribute” class. Custom attribute helps to tag a property or class or method to identify the respective members at run time based on type.
Below Example helps to understand better.
In below example, the same business object can be used in 2 different entities to invoke actions specific to entity.
Class which has methods to read property values based on type.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace BusinessAttributes
{
public class Attribute
{
//To read the value of a given property and type
public object ReadPropertyValue(Object argBusinessObject, Type atrType)
{
Type objType = argBusinessObject.GetType();
var properties = (from memInfo in objType.FindMembers(MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, null, null)
where memInfo.GetCustomAttributes(atrType, true).Count() > 0 &&
memInfo.GetCustomAttributes(atrType, true).All((o) =>
{ if (o.ToString().Trim().ToUpper() == atrType.ToString().Trim().ToUpper()) { return true; } return false; })
select memInfo);
if (properties.Count() == 0)
throw new Exception("Business Property of type \"" + atrType.ToString() + "\" not found");
if (properties.Count() > 1)
throw new Exception("Business Property of type \"" + atrType.ToString() + "\" found more than one");
return objType.InvokeMember(properties.First().Name, BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.Public, null, argBusinessObject, null);
}
//To return custom attribute objects list
public IList<Object> GetCustomAttribute(Object argBusinessObject, Type atrType)
{
Type objType = argBusinessObject.GetType();
var properties = (from memInfo in objType.FindMembers(MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, null, null)
where memInfo.GetCustomAttributes(atrType, true).Count() > 0 &&
memInfo.GetCustomAttributes(atrType, true).All((o) =>
{ if (o.ToString().Trim().ToUpper() == atrType.ToString().Trim().ToUpper()) { return true; } return false; })
select memInfo);
if (properties.Count() == 0)
throw new Exception("Business Property of type \"" + atrType.ToString() + "\" not found");
if (properties.Count() > 1)
throw new Exception("Business Property of type \"" + atrType.ToString() + "\" found more than one");
var customAttribute =
(from att in properties.First().GetCustomAttributes(atrType, true)
where att.GetType().ToString().Trim().ToUpper() == atrType.ToString().Trim().ToUpper()
select att);
return customAttribute.ToList();
}
}
}
Logger (Entity) class extending the BusinessAttributes.Attribute class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace DBLogger
{
public class Logger : BusinessAttributes.Attribute
{
public Object LogObject
{
set;
get;
}
//reading the employee details from object based on custom attribute type
public string ReadDetails()
{
return "Log Information - " + ReadPropertyValue(LogObject, typeof(DBLogger.LogID)) + " - " + ReadPropertyValue(LogObject, typeof(DBLogger.LogDesc));
}
}
public class LogID : Attribute { };
public class LogDesc : Attribute { };
}
Employee (Entity) class extending the BusinessAttributes.Attribute class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace EmployeeLib
{
public class Employee : BusinessAttributes.Attribute
{
public Object EmployeeObject
{
set;
get;
}
//reading the employee details from object based on custom attribute type
public string ReadDetails()
{
IList<Object> dt = GetCustomAttribute(EmployeeObject, typeof(EmpID));
EmpID objEmpID = dt[0] as EmpID;
if (objEmpID.isActive)
return "Employee Information (Active) - " + ReadPropertyValue(EmployeeObject, typeof(EmpID)) + " - " + ReadPropertyValue(EmployeeObject, typeof(EmpName));
else
return "Employee Information (Inactive) - " + ReadPropertyValue(EmployeeObject, typeof(EmpID)) + " - " + ReadPropertyValue(EmployeeObject, typeof(EmpName));
}
}
public class EmpID : Attribute
{
public bool isActive { get; set; }
public EmpID(bool blnActive)
{
isActive = blnActive;
}
};
public class EmpName : Attribute
{ };
}
User Interface (Windows form)
//The common business object which can be used in 2 entities
CommonBA objCommonBA = null;
//when used clicks on "Log" button
private void button1_Click(object sender, EventArgs e)
{
try
{
//creating an object for Log entity and setting the shared business object as Log Object
DBLogger.Logger objLogger = new DBLogger.Logger() { LogObject = objCommonBA };
//displaying the details of the log object
MessageBox.Show(objLogger.ReadDetails());
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
}
//when used clicks on "Employee" button
private void button2_Click(object sender, EventArgs e)
{
try
{
//creating an object for Employee entity and setting the shared business object as Employee object
EmployeeLib.Employee objEmp = new EmployeeLib.Employee() { EmployeeObject = objCommonBA };
//displaying the employee details.
MessageBox.Show(objEmp.ReadDetails());
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
}
//on form load
private void Form1_Load(object sender, EventArgs e)
{
//creating the shared business object
objCommonBA = new CommonBA() { ID = 1234, Desc = "srinivas" };
}
}
//The Business class
public class CommonBA
{
[DBLogger.LogID]
[EmployeeLib.EmpID(true)]
//ID attribute and tagged that this property can be used as Log ID in case of
//log entity and the same as employee id in employee entity
public int ID
{
get;
set;
}
[DBLogger.LogDesc]
[EmployeeLib.EmpName]
//Desc attribute and tagged that this property can be used as Log Description in case of
//log entity and the same as employee name in employee entity
public string Desc
{
get;
set;
}
}
No comments:
Post a Comment