-
Attributes provide a powerful method of associating declarative information with code. We need two properties in our attribute.
-
Key which we need to pass to read data from dictionary, If user do not provide this key then we will assume that name of property/field is key.
Enumeration that defines dictionary to read data from which will default to query string.
public class PageProperty : Attribute
{
private DictionaryType readFrom = DictionaryType.QueryString;
privatestring key;
publicstring Key
{
get
{
return key;
}
set
{
key = value;
}
}
public DictionaryType ReadFrom
{
get
{
return readFrom;
}
set
{
readFrom = value;
}
}
}
Once we have above class we can tag fields in our page with above attribute.
[PageProperty(ReadFrom = DictionaryType.Cookie)]
public int userId;
Reading attributes using reflection and populating values:
-
We will use reflection to inspect page class to find all property or public fields with PageProperty Attribute.
-
Next step will be to get key and DictionaryType.
-
And once we know source and target to populate and we will get information from appropriate dictionary and populate it.
We will warp this logic into a small static class with static Read method, which takes reference of page object.
public static void Read(object pageObject)
{
// read for all fields.
FieldInfo[] fields = (pageObject.GetType()).GetFields();
foreach (FieldInfo fieldInfo in fields)
{
object[] attributes = fieldInfo.GetCustomAttributes(typeof(PageProperty), false);
if (attributes.Length > 0)
{
PageProperty pageProperty = attributes[0] as PageProperty;
string key = pageProperty.Key;
if (key == null) key = fieldInfo.Name;
object val = getValue(key, pageProperty.ReadFrom);
if (val != null)
{
fieldInfo.SetValue(pageObject, changeType(val, fieldInfo.FieldType));
}
}
}
}
Retriving value from Dictionary:
Since we are using flags user might specify more than one place to read from, for example user might specify following:
[PageProperty(ReadFrom = DictionaryType.QueryString | DictionaryType.Cookie)]
To handle this we will go through all selected enumerations and return first with value, so in above mentioned example if query string value was present it will return query string value, otherwise it will return value from cookie.
private static object getValue(string key, DictionaryType readFrom)
{
if ((readFrom & DictionaryType.QueryString) == DictionaryType.QueryString &&
HttpContext.Current.Request.QueryString[key] !=null)
{
return HttpContext.Current.Request.QueryString[key];
}
elseif ((readFrom & DictionaryType.Form) == DictionaryType.Form &&
HttpContext.Current.Request.Form[key] !=null)
{
return HttpContext.Current.Request.Form[key];
}
}
How to use Property Reader in your web page?
-
Drop Jigar.Web.PagePropertyReader.dll in to bin directory of your web project.
-
In your Page class add following line in Pre_Init Event.
PropertyReader.Read(this);
Alternatively you can also create PageBase class by inheriting from System.Web.UI.Page and override PreInit event.
-
Finally in your page just create public property or field with PageProperty Attribute and you are done.
Source code includes sample web application, which shows usage of PropertyReader. It also includes test page with different senerios.
What about performance cost associated with reflection?
Reflection is definitely going to add some performance cost to your application, you will have to analyze value vs. cost analysis for your application and decide best for you.
Instead of reflection you might also want to try using Reflection.Emit to improve performance.