patterncsharpMinor
Using Custom Attributes to Populate Members from IDataReader
Viewed 0 times
idatareadercustomattributespopulateusingmembersfrom
Problem
Just learned how to use custom attributes in C# and the first useful thing I did with it was to make a class object representing a database table. The constructor can accept an
IDataReader and populate the members based on the custom attribute. Is this a good usage of custom attributes? [AttributeUsage(AttributeTargets.Property)]
public class DatabaseField: Attribute
{
public string Name { get; set; }
public DatabaseField( string name )
{
Name = name;
}
}
public class Employee
{
[DatabaseField("Employee_ID")]
public string EmployeeId { get; set; }
[DatabaseField("LogonId")]
public string Username { get; set; }
[DatabaseField("Email")]
public string EmailAddress { get; set; }
[DatabaseField("NAME")]
public string DisplayName { get; set; }
[DatabaseField("First_Name")]
public string FirstName { get; set; }
[DatabaseField("Middle_Name")]
public string MiddeName { get; set; }
[DatabaseField("Last_Name")]
public string LastName { get; set; }
[DatabaseField("Name_Suffix")]
public string NameSuffix { get; set; }
[DatabaseField("Job_Title")]
public string JobTitle { get; set; }
[DatabaseField("Department")]
public string Department { get; set; }
[DatabaseField("Emp_Type")]
public string EmployeeType { get; set; }
[DatabaseField("SupervisorID")]
public string ManagerId { get; set; }
public Employee( IDataReader reader )
{
foreach( PropertyInfo prop in typeof(Employee).GetProperties() )
{
foreach( object attr in prop.GetCustomAttributes(true) )
{
DatabaseField field = attr as DatabaseField;
if( null != field )
{
object value = reader[field.Name];
prop.SetValue(this, value == DBNull.Value ? null : value, null);
}
}
}
}
}Solution
public class DatabaseField: AttributeAccording to the naming guidelines, the names of attribute classes should end with
Attribute, so this class should be called DatabaseFieldAttribute.public string Name { get; set; }I don't see any reason why the setter should be public, so I would make it private.
public Employee( IDataReader reader )I don't think all this code should be here. Instead, it should be in a library that's not specific to your types.
Have you considered adding the knowledge of your naming conventions to your code, so that not all properties need the attribute?
Also, I would go the other way around: for each column in the reader, find the appropriate property to set. That way, if your type is missing a property, you can learn about it.
foreach( object attr in prop.GetCustomAttributes(true) )I would use the generic extension method
GetCustomAttribute() here, to simplify your code:var attr = prop.GetCustomAttribute(true);if( null != field )There is not reason to use Yoda conditions in C#. The issue they're addressing is that buggy code like
if (field = null) is valid C and C++. But it's not valid C#.Code Snippets
public class DatabaseField: Attributepublic string Name { get; set; }public Employee( IDataReader reader )foreach( object attr in prop.GetCustomAttributes(true) )var attr = prop.GetCustomAttribute<DatabaseFieldAttribute>(true);Context
StackExchange Code Review Q#66388, answer score: 5
Revisions (0)
No revisions yet.