怎么联系百度推广,荆门seo,罗湖网站制作公司,ico网站建设1、Attributes语义学
程序语言经历多次革命#xff0c;多重继承渐渐消失于近代程序语言中#xff0c;其空下的位置也正式由接口(Interface)所取代。另一方面#xff0c;对象持久机制也慢慢成为程序语言的基本建设之一#xff0c;不过目前出现一个诡异的现象#xff0c;在…1、Attributes语义学
程序语言经历多次革命多重继承渐渐消失于近代程序语言中其空下的位置也正式由接口(Interface)所取代。另一方面对象持久机制也慢慢成为程序语言的基本建设之一不过目前出现一个诡异的现象在java语言中类要支持Serilization就必须声明成如下形式
public class ClassA implements java.io.Serializable
有趣的是Serializable界面中并未声明任何须实现的函数纯粹只是一个空接口这一点似乎不太符合接口的正常用法。的确Serializable被当成是识别证使用.NET Framework中此类运用被明确分割成另一种机制它的名称叫Attribute。Attribute的出现是为了由接口或抽象类中分离出标签类型的运行例如java.io.Serializable是一个接口但其真正的用途却是为此类贴上一个标签代表着此类支持Serializable能力。Serializable界面在.NET Framework则被正名为SerializableAttribute相较两者.NET Framework在语意上似乎显得明确许多。笔者喜欢将Attribute成之为标签便利贴如果你觉得亲切的话因为它可以贴在类、方法、属性、成员变量之上告知处理者应该何如处理目标物。此处须特别澄清一点Attribute本身是被动物简单地说是其自身不可能知道贴在哪一个目标上所以中Attribute中是无法存取目标物的。
2、看看Attribute能做什么
用户预定义的Attribute必须继承自System.Attribute类其构造函数所接受的参数代表着使用该Attribute时所须传入的参数程序1-1是一个简单的Attribute范例。
using System;
using System.ComponentModel;
namespace AttributeFullDemo
{
[AttributeUsage(AttributeTargets.Class,Inheritedfalse,AllowMultiplefalse)]
public class ClassShowProcessAttribute:Attribute
{
private bool show false;
public bool Show
{
get{
return show;
}
}
public ClassShowProcessAttribute(bool show)
{
this.show show;
}
}
}
有趣的是用户预定义的Attribute本身也贴上了另一个Attribute不过这在语意上并不冲突AttributeUsage代表着此Attribute所适用的情况其第一个参数是该Attribute所使用的范围其可以是类、方法、属性等等第二个参数代表着当Attribute被贴在目标物上后继承至目标物的继承者是否会连此Attribute一并继承第三个参数代表此Attribute是否允许重复贴在同一目标物上意思是说是否允许同时贴两个以上同样的Attribute在目标物上。基本上Attribute是绑定于Type上设计人员得通过Type.GetCustomAttributes函数来判定此Type中拥有哪些Attribute程序1-2、1-3是使用ClassShowProcessAttribute的范例。
1-2贴上ClassShowProcessAttribute的类范例
using System;
namespce AttributeFullDemo
{
[ClassShowProcess(true)]
public class AttrClassTest
{
public AttrClassTest(){}
}
} 1-3: 使用贴上ClassShowProcessAttribute类的范例
private void btnTestClass_Click(object sender,System.EventArgs e)
{
object[] o new object[]{
new AttrClassTest(),
new AttrClassTest(),TEST
};
foreach(object item in o)
{
ClassShowProcessAttribute[] attr
(ClassShowProcessAttribute[])item.GetType().GetCustomAttributes(typeof(ClassShowProcessAttribute),false);
if(attr.Length!0)
if(attr[0].Show)
textBox1.Text \r\n item.ToString();
}
} 程序1-3中创建了一个object类型的数组在其中放入了两个AttrClassTest对象及一个string对象接着遍历此对象数组一一调用Type.GetCustomAttributes函数GetCustomAttributes函数拥有两个重载函数其中之一接受inherited参数此参数对应至AttributeUsage的inherited参数。另一个则接受inherited及一个Type参数此处使用的是第二个重载函数并指定其Type为ClassShowProcessAttribute这可以使返回值仅限于此Attribute。此处有一点须特别注意Attribute对象的创建时机是设计者调用GetCustomAttributes函数时其拥有的两个重载函数代表两种创建方式第一种方式会创建该Type的所有Attributes对象除非有特殊需求否则设计人员应该尽量使用第二种减少创建无意义的Attribute对象。
Attribute in Member Field
除了绑定至类外Attribute也可以绑定至成员变量上程序2-1,程序2-2展现了此种应用 2-1 可绑定至成员变量上的Attribute范例
using System;
using System.ComponentModel;
using System.Reflection;
namespace AttributeFullDemo
{
public interface IFiledShow
{
string Show(object o);
}
[AttributeUsage(AttributeTargets.File|AttributeTargets.Property,Inheritedfalse,AllowMultiplefalse)]
public class FiledShowAttribute:Attribute
{
private bool show false;
private Type showClass null;
public bool Show
{
get
{
return show;
}
}
public Type ShowClass
{
get{
return showClass;
}
}
public IFileShow CreateShowInstance()
{
object o;
ConstructorInfo cinfo showClass.GetConstructor(new Type[]{});
o cinfo.Invoke(null);
return (IFileShow)o;
}
public FiledShowAttribute(bool show,Type showClass)
{
show show;
showClass showClass;
if(showClassnull)
{
throw new Exception(must provides showClass!!);
}
}
}
}
2-1 贴上FiledShowAttribute的类范例 using System;
using System.ComponentModel;
namespace AttributeFullDemo
{
public IFiledShow.Show(object o)
{
return o.ToString();
}
}
public class AttrFiledTest
{
[FiledShow(true,Typeof(StringFiledShow))]
public int number 0;
public AttrFiledTest()
{
}
}
此程序也展现了另一种Attribute类型的应用它接受一个Type参数这代表着设计人员于是用此Attribute时可以指定一个自定义的Type来改变其显示的行为设计人员也可以提供一系列的预先定义的Type供用户运用这将Attribute带往另一个较为复杂且高扩展性的应用面程序2-4的范例展示了这一点。 2-4 是用贴上FiledShowAttribute类的范例
private void btnTestFileld_Click(object sender,System.Events e)
{
AttrFiledTest[] o new AttrFiledTest[]{ new AttrFieldTest(),new AttrFieldTest()};
o[0].number 15;
o[1].number30;
foreach(AttrFiledTest item in o)
{
FiledShowAttribute[] fattr(FieldShowAttribute[])field.GetCustomAttributes(typeof(FieldShowAttribute),false);
if(fattr.Length!0)
{
textBox1.Text \r\n field.Name fattr[0].CreateShowInstance().Show(field.GetValue(item));
}
}
}
这种概念是将原本应该有由是用端处理的工作交由另一个类来处理这可以有效地切割应用程序给予较高的扩展性及明确的定位。不过此范例并不是一个良好的设计因为其在寻找Attribute时会为每一个Attribute.Type创建一个实体因而有滥用内存之嫌。要改善这一点设计人员可以于Attribute中预定义一个静态函数并要求传入的Attribute.Type类型必须拥有一个静态函数程序2-5和2-6是修改后的范例。 2-5 修改后的FieldShowAttribute范例
using System;
using System.ComponentModel;
using System.Reflection;
namespace AttributeFullDemo
{
public interface IFieldShow
{
string Show(object o);
}
[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property,Inheritedfalse,AllowMultiplefalse)]
public class FieldShowAttribute:Attribute
{
private bool show false;
private Type showClass null;
public bool Show
{
get{
return show;
}
}
public Type ShowClass
{
get{
return showClass;
}
}
public IFieldShow CreateShowInstance()
{
object o;
ConstructorInfo cinfo showClass.GetConstructor(new Type[]{});
o cinfo.Invoke(null);
return (IFieldShow)o;
}
public static string ShowValue(FieldShowAttribute attr,object o,FieldInfo valueObject)
{
MethodInfo mi attr.ShowClass.GetMothod(Show,BindingFlags.Static|BindingFlags.Public);
return (string)mi.Invoke(null,new object[] {valueObject.GetValue(o)});
}
public FieldShowAttribute(bool show ,Type showClass)
{
show show;
showClass showClass;
if(showClassnull) throw new Exception(must provides showClass!!);
}
}
} 2-6 修改后贴上FieldShowAttribute类的范例
using System;
using System.ComponentModel;
namespace AttributeFullDemo
{
public class StringFieldShow:IFieldShow
{
string IFieldShow.Show(object o)
{
return o.ToString();
}
}
public class StringFieldShow2
{
public static string Show(object o)
{
return o.ToString();
}
}
public class AttrFieldTest
{
[FieldShow(true,typeof(StringFieldShow2))]
public int number0;
public AttrFieldTest(){}
}
} 此范例使用了静态函数及Reflection技术来实现前面所提及的想法现在使用端的范例就不需要为每一个Attribute创建一个ShowClass对象了见下面程序2-7
2-7 使用贴上FieldShowAttribute类的范例
private void btnTestField_Click(object sender,System.EventArgs e)
{
AttrFileTest[] o new AttrFieldTest[] {new AttrFieldTest(), new AttrFieldTest()};
o[0].number 15;
o[1].number 16;
foreach(AttrFieldTest item in o)
{
foreach(Field field in item.GetType().GetFields())
{
FieldShowAttribute[] fattr
(FieldShowAttribute[])field.GetCustomAttributes(typeof(FieldShowAttribte),false);
if(fattr.Length !0)
textBox1.Test \r\n FieldShowAttribute.ShowValue(fattr[0],item,field);
}
}
}