在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
以下部分内容及代码来源于《C#技术揭秘》(Inside C# Sencond Edition) 定义属性:
属性实际上是一个派生自System.Attribute基类的类。System.Attribute类含有几个用于访问和检查自定义属性的方法。尽管你有权将任何类定义为属性,但是按照惯例来说,从System.Attribute派生类是有意义的。示例如下:
public enum RegHives
{
HKEY_CLASSES_ROOT,
HKEY_CURRENT_USER,
HKEY_LOCAL_MACHINE,
HKEY_USERS,
HKEY_CURRENT_CONFIG
}
public class RegKeyAttribute : Attribute
{
public RegKeyAttribute(RegHives Hive, String ValueName)
{
this.Hive = Hive;
this.ValueName = ValueName;
}
protected RegHives hive;
public RegHives Hive
{
get { return hive; }
set { hive = value; }
}
protected String valueName;
public String ValueName
{
get { return valueName; }
set { valueName = value; }
}
}
我们在这里添加了不同注册表的枚举、属性类的构造器以及两个特性(Property)。在定义属性时你可以做许许多多的事情,下面我们看看如何在运行时查询属性。要想在运行时查询类型或成员所附着的属性,必须使用反射.
查询类属性:
假设你希望定义一个属性,这个属性定义了将在其上创建对象的远程服务器。如果没有这个属性,就要把此信息保存在一个常量中或是一个应用程序的资源文件中。通过使用属性,只需用以下方法标注出类的远程服务器名即可:
using System;
namespace QueryAttribs
{
public enum RemoteServers
{
JEANVALJEAN,
JAVERT,
COSETTE
}
public class RemoteObjectAttribute : Attribute
{
public RemoteObjectAttribute(RemoteServers Server)
{
this.server = Server;
}
protected RemoteServers server;
public string Server
{
get
{
return RemoteServers.GetName(
typeof(RemoteServers), this.server);
}
}
}
[RemoteObject(RemoteServers.COSETTE)]
class MyRemotableClass
{
}
class Test
{
[STAThread]
static void Main(string[] args)
{
Type type = typeof(MyRemotableClass);
foreach (Attribute attr in
type.GetCustomAttributes(true))
{
RemoteObjectAttribute remoteAttr =
attr as RemoteObjectAttribute;
if (null != remoteAttr)
{
Console.WriteLine(
"Create this object on {0}.",
remoteAttr.Server);
}
}
Console.ReadLine();
}
}
}
运行结果为:
Creat this object on COSETTE。
注意:在这个例子中的属性类名具有Attribute后缀。但是,当我们将此属性附着给类型或成员时却不包括Attribute后缀。这是C#语言的设计者提供的简单方式。当编译器看到一个属性被附着给一个类型或成员时,它会搜索具有指定属性名的System.Attribute派生类。如果编译器没有找到匹配的类,它就在指定的属性名后面加上Attribute,然后再进行搜索。因此,常见的使用做法是将属性类名定义为以Attribute结尾,在使用时忽略名称的这一部分。以下的代码都采用这种命名方式。
查询方法属性:
在下面这个例子中,我们使用属性将方法定义为可事务化的方法,只要存在TransactionableAttribute属性,代码就知道具有这个属性的方法可以属于一个事务。
using System;
using System.Reflection;
namespace MethodAttribs
{
public class TransactionableAttribute : Attribute
{
public TransactionableAttribute()
{
}
}
class SomeClass
{
[Transactionable]
public void Foo()
{}
public void Bar()
{}
[Transactionable]
public void Goo()
{}
}
class Test
{
[STAThread]
static void Main(string[] args)
{
Type type = Type.GetType("MethodAttribs.SomeClass");
foreach (MethodInfo method in type.GetMethods())
{
foreach (Attribute attr in
method.GetCustomAttributes(true))
{
if (attr is TransactionableAttribute)
{
Console.WriteLine(
"{0} is transactionable.",
method.Name);
}
}
}
Console.ReadLine();
}
}
}
运行结果如下:
Foo is transactionable.
Goo is transactionable.
查询字段属性:
假设有一个类含有一些字段,我们希望将它们的值保存进注册表。为此,可以使用以枚举值和字符串为参数的构造器定义一个属性,这个枚举值代表正确的注册表hive,字符串代表注册表值名称。在运行时可以查询字段的注册表键。
using System;
using System.Reflection;
namespace FieldAttribs
{
public enum RegHives
{
HKEY_CLASSES_ROOT,
HKEY_CURRENT_USER,
HKEY_LOCAL_MACHINE,
HKEY_USERS,
HKEY_CURRENT_CONFIG
}
public class RegKeyAttribute : Attribute
{
public RegKeyAttribute(RegHives Hive, String ValueName)
{
this.Hive = Hive;
this.ValueName = ValueName;
}
protected RegHives hive;
public RegHives Hive
{
get { return hive; }
set { hive = value; }
}
protected String valueName;
public String ValueName
{
get { return valueName; }
set { valueName = value; }
}
}
class SomeClass
{
[RegKey(RegHives.HKEY_CURRENT_USER, "Foo")]
public int Foo;
public int Bar;
}
class Test
{
[STAThread]
static void Main(string[] args)
{
Type type = Type.GetType("FieldAttribs.SomeClass");
foreach (FieldInfo field in type.GetFields())
{
foreach (Attribute attr in
field.GetCustomAttributes(true))
{
RegKeyAttribute rka =
attr as RegKeyAttribute;
if (null != rka)
{
Console.WriteLine(
"{0} will be saved in"
+ " {1}////{2}",
field.Name,
rka.Hive,
rka.ValueName);
}
}
}
Console.ReadLine();
}
}
}
运行结果为:
Foo will be saved in HKEY_CURRENT_USER//Foo
大家可以看到,用属性来标注类、方法、字段,既可以把用户的自定义信息附属在实体上,又可以在运行时动态的查询。下面我将讲一些C#中默认的预定义属性,见下表:
下面介绍几种常用的属性
1.[STAThread]和[MTAThread]属性
class Class1
{
[STAThread]
Static void Main( string[] args )
{
}
}
使用STAThread属性将程序的默认线程模型指定为单线程模型。注意,线程模型只影响使用COM interop的应用程序,将这个属性应用于不使用COM interop的程序将不会产生任何效果。
2. AttributeUsage属性
除了用于标注常规C#类型的自定义属性以外,还可以使用AttributeUsage属性定义你使用这些属性的方式。文件记录的AttributeUsage属性调用用法如下:
[AttributeUsage( validon , AllowMutiple = allowmutiple , Inherited = inherited )]
Validon参数是AttributeTargets类型的,这个枚举值的定义如下:
public enum AttributeTargets
{
Assembly = 0x0001,
Module = 0x0002,
Class = 0x0004,
Struct = 0x0008,
Enum = 0x0010,
Constructor = 0x0020,
Method = 0x0040,
Property = 0x0080,
Field = 0x0100,
Event = 0x200,
Interface = 0x400,
Parameter = 0x800,
Delegate = 0x1000,
All = Assembly | Module | Class | Struct | Enum | Constructor| Method | Property| Filed| Event| Interface | Parameter | Deleagte ,
ClassMembers = | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface
}
AllowMultiple决定了可以在单个字段上使用某个属性多少次,在默认情况下,所有的属性都是单次使用的。示例如下:
[AttributeUsage( AttributeTargets.All , AllowMultiple = true )]
public class SomethingAttribute : Attribute
{
public SomethingAttribute( string str )
{
|
请发表评论