声明式编程是一种更简单、更精练的描述软件程序行为的方式,它意味着可以使用声明、而非指令的方式来定义程序的行为。C#中大部分编程都是命令式编程,即通过编写方法来定义程序的行为。我们可以通过使用特性,来在C#中实现声明式编程,它更易于实现、阅读和维护。
.NET框架本身已经为我们提供了大量的特性,我们可以利用这些特性非常方便的实现声明式编程;当.NET框架提供的特性不能满足我们的需求时,我们也可以自己定制特性。
首先,我们来看一个使用.NET框架提供的特性的例子,看以下代码。
public class ClassWithAttribute
{
[Conditional("DEBUG")]
[Obsolete("This Method should not be called yet.")]
public void Ouput()
{
Console.WriteLine("Hello World");
}
}
上面的代码使用了两个特性,第一个特性Conditional,表明方法只在DEBUG模式下才会被调用;第二个特性Obsolete,表明方法已经被废弃,不应该再调用,这两个特性都是.NET框架提供的,我们可以很方便的使用它们。
然后,我们来看一个自己定制特性的例子,看以下代码。
[AttributeUsage(AttributeTargets.All)]
public class TestAttribute : System.Attribute
{
private string m_strOutputField;
public string OutputField
{
get { return m_strOutputField; }
set { m_strOutputField = value; }
}
public TestAttribute(string fielaName)
{
m_strOutputField = fielaName;
}
}
[Test("Name")]
public class Employee
{
private string m_strName;
public string Name
{
get { return m_strName; }
set { m_strName = value; }
}
private string m_strSex;
public string Sex
{
get { return m_strSex; }
set { m_strSex = value; }
}
private string m_strAddress;
public string Address
{
get { return m_strAddress; }
set { m_strAddress = value; }
}
public Employee(string name, string sex, string address)
{
m_strName = name;
m_strSex = sex;
m_strAddress = address;
}
}
上述代码中,定义了一个特性,名为TestAttribute,它派生自System.Attribute,包含一个名为OutputField的属性,然后定义了一个用于表示员工信息的类,包含Name、Sex和Address三个属性,其中,这个类被Test特性所修饰,特性构造函数中的值是“Name”。
下面是测试函数。
private static void OutputEmpInfo()
{
Employee emp = new Employee("Wing", "M", "BeiJing");
//get attribute info.
object[] arrAttribute = typeof(Employee).GetCustomAttributes(typeof(TestAttribute), false);
string strFieldName = string.Empty;
if (arrAttribute != null && arrAttribute.Length > 0)
{
TestAttribute attribute = arrAttribute[0] as TestAttribute;
strFieldName = attribute.OutputField;
}
if (string.IsNullOrEmpty(strFieldName))
{
return;
}
//get property by reflection.
PropertyInfo propInfo = typeof(Employee).GetProperty(strFieldName);
if (propInfo == null)
{
return;
}
//output value.
object outputValue = propInfo.GetValue(emp, null);
Console.WriteLine(outputValue.ToString());
}
上述代码中,首先定义了一个Employee类型的对象,然后查找Employee类型中Test特性的信息,并将特性的OutputField属性返回,然后通过反射,取得Employee类型对象中的信息,将其输出。
当我们将特性中的OutputField属性设置为“Name”时,程序会输出Employee对象的Name属性,当我们将特性的OutputField属性设置为“Sex”或者“Address”时,程序会输出Employee对象对应的属性的值。
当一个简单的声明就可以表明我们的意图时,采用声明式的方法可以避免重复性代码。如果针对某一种功能,在程序中只需要一两次,那么编写一些简单的函数就可以了,如果这些功能是在大量的地方都需要使用,那么通过算法加声明式的解决方案将会为我们节省大量的时间和精力。
总结:声明式编程是一个强大的工具,当可以使用特性来声明我们的意图时,实际上也就避免了在多个类似的手工编写的算法中,犯逻辑错误的可能。声明式编程会创建更为可读和清晰的代码。这意味着更少的错误。如果可以使用.NET框架中定义的特性,那么我们就应该积极的使用。如果不能,则可以考虑选择创建我们自己的特性类,然后再将来使用它创建相同的行为。