开发中灵活使用属性类
什么是属性类?
从抽象类System.Attribute派生出来的类(无论是直接的还是间接的)都称为属性类(MSDN中的定义)。
属性类的名称一般都带有Attribute后缀,但使用的时候可以包含也可以忽略,如果你自己起的名字没有这个后缀,则需要全称来区分了。如果不怕输入麻烦,建议还是不管是否有后缀,都输入全称为好,这样可以减少歧义。
在.NET框架中差不多定义了200个Attribute相关类,可见Attribute的应用十分广泛,它的全图在MSDN中如下:
System.Attribute
System.AttributeUsageAttribute
System.CLSCompliantAttribute
System.ComponentModel.AmbientValueAttribute
System.ComponentModel.BindableAttribute
System.ComponentModel.BrowsableAttribute
System.ComponentModel.CategoryAttribute
System.ComponentModel.DefaultEventAttribute
System.ComponentModel.DefaultPropertyAttribute
System.ComponentModel.DefaultValueAttribute
System.ComponentModel.DescriptionAttribute
System.ComponentModel.Design.Serialization.DesignerSerializerAttribute
System.ComponentModel.Design.Serialization.RootDesignerSerializerAttribute
System.ComponentModel.DesignerAttribute
System.ComponentModel.DesignerCategoryAttribute
System.ComponentModel.DesignerSerializationVisibilityAttribute
System.ComponentModel.DesignOnlyAttribute
System.ComponentModel.DesignTimeVisibleAttribute
System.ComponentModel.EditorAttribute
System.ComponentModel.EditorBrowsableAttribute
System.ComponentModel.ImmutableObjectAttribute
System.ComponentModel.InheritanceAttribute
System.ComponentModel.InstallerTypeAttribute
System.ComponentModel.LicenseProviderAttribute
System.ComponentModel.ListBindableAttribute
System.ComponentModel.LocalizableAttribute
System.ComponentModel.MergablePropertyAttribute
System.ComponentModel.NotifyParentPropertyAttribute
System.ComponentModel.ParenthesizePropertyNameAttribute
System.ComponentModel.PropertyTabAttribute
System.ComponentModel.ProvidePropertyAttribute
System.ComponentModel.ReadOnlyAttribute
System.ComponentModel.RecommendedAsConfigurableAttribute
System.ComponentModel.RefreshPropertiesAttribute
System.ComponentModel.RunInstallerAttribute
System.ComponentModel.ToolboxItemAttribute
System.ComponentModel.ToolboxItemFilterAttribute
System.ComponentModel.TypeConverterAttribute
System.ContextStaticAttribute
System.Diagnostics.ConditionalAttribute
System.Diagnostics.DebuggableAttribute
System.Diagnostics.DebuggerHiddenAttribute
System.Diagnostics.DebuggerStepThroughAttribute
System.Drawing.ToolboxBitmapAttribute
System.EnterpriseServices.ApplicationAccessControlAttribute
System.EnterpriseServices.ApplicationActivationAttribute
System.EnterpriseServices.ApplicationIDAttribute
System.EnterpriseServices.ApplicationNameAttribute
System.EnterpriseServices.ApplicationQueuingAttribute
System.EnterpriseServices.AutoCompleteAttribute
System.EnterpriseServices.CompensatingResourceManager.ApplicationCrmEnabledAttribute
System.EnterpriseServices.ComponentAccessControlAttribute
System.EnterpriseServices.COMTIIntrinsicsAttribute
System.EnterpriseServices.ConstructionEnabledAttribute
System.EnterpriseServices.DescriptionAttribute
System.EnterpriseServices.EventClassAttribute
System.EnterpriseServices.EventTrackingEnabledAttribute
System.EnterpriseServices.ExceptionClassAttribute
System.EnterpriseServices.IISIntrinsicsAttribute
System.EnterpriseServices.InterfaceQueuingAttribute
System.EnterpriseServices.JustInTimeActivationAttribute
System.EnterpriseServices.LoadBalancingSupportedAttribute
System.EnterpriseServices.MustRunInClientContextAttribute
System.EnterpriseServices.ObjectPoolingAttribute
System.EnterpriseServices.PrivateComponentAttribute
System.EnterpriseServices.SecureMethodAttribute
System.EnterpriseServices.SecurityRoleAttribute
System.EnterpriseServices.SynchronizationAttribute
System.EnterpriseServices.TransactionAttribute
System.FlagsAttribute
System.LoaderOptimizationAttribute
System.Management.Instrumentation.IgnoreMemberAttribute
System.Management.Instrumentation.InstrumentationClassAttribute
System.Management.Instrumentation.InstrumentedAttribute
System.Management.Instrumentation.ManagedNameAttribute
System.MTAThreadAttribute
System.NonSerializedAttribute
System.ObsoleteAttribute
System.ParamArrayAttribute
System.Reflection.AssemblyAlgorithmIdAttribute
System.Reflection.AssemblyCompanyAttribute
System.Reflection.AssemblyConfigurationAttribute
System.Reflection.AssemblyCopyrightAttribute
System.Reflection.AssemblyCultureAttribute
System.Reflection.AssemblyDefaultAliasAttribute
System.Reflection.AssemblyDelaySignAttribute
System.Reflection.AssemblyDescriptionAttribute
System.Reflection.AssemblyFileVersionAttribute
System.Reflection.AssemblyFlagsAttribute
System.Reflection.AssemblyInformationalVersionAttribute
System.Reflection.AssemblyKeyFileAttribute
System.Reflection.AssemblyKeyNameAttribute
System.Reflection.AssemblyProductAttribute
System.Reflection.AssemblyTitleAttribute
System.Reflection.AssemblyTrademarkAttribute
System.Reflection.AssemblyVersionAttribute
System.Reflection.DefaultMemberAttribute
System.Resources.NeutralResourcesLanguageAttribute
System.Resources.SatelliteContractVersionAttribute
System.Runtime.CompilerServices.AccessedThroughPropertyAttribute
System.Runtime.CompilerServices.CompilationRelaxationsAttribute
System.Runtime.CompilerServices.CompilerGlobalScopeAttribute
System.Runtime.CompilerServices.CustomConstantAttribute
System.Runtime.CompilerServices.DecimalConstantAttribute
System.Runtime.CompilerServices.DiscardableAttribute
System.Runtime.CompilerServices.IndexerNameAttribute
System.Runtime.CompilerServices.MethodImplAttribute
System.Runtime.CompilerServices.RequiredAttributeAttribute
System.Runtime.InteropServices.AutomationProxyAttribute
System.Runtime.InteropServices.BestFitMappingAttribute
System.Runtime.InteropServices.ClassInterfaceAttribute
System.Runtime.InteropServices.CoClassAttribute
System.Runtime.InteropServices.ComAliasNameAttribute
System.Runtime.InteropServices.ComCompatibleVersionAttribute
System.Runtime.InteropServices.ComConversionLossAttribute
System.Runtime.InteropServices.ComEventInterfaceAttribute
System.Runtime.InteropServices.ComImportAttribute
System.Runtime.InteropServices.ComRegisterFunctionAttribute
System.Runtime.InteropServices.ComSourceInterfacesAttribute
System.Runtime.InteropServices.ComUnregisterFunctionAttribute
System.Runtime.InteropServices.ComVisibleAttribute
System.Runtime.InteropServices.DispIdAttribute
System.Runtime.InteropServices.DllImportAttribute
System.Runtime.InteropServices.FieldOffsetAttribute
System.Runtime.InteropServices.GuidAttribute
System.Runtime.InteropServices.IDispatchImplAttribute
System.Runtime.InteropServices.ImportedFromTypeLibAttribute
System.Runtime.InteropServices.InAttribute
System.Runtime.InteropServices.InterfaceTypeAttribute
System.Runtime.InteropServices.LCIDConversionAttribute
System.Runtime.InteropServices.MarshalAsAttribute
System.Runtime.InteropServices.OptionalAttribute
System.Runtime.InteropServices.OutAttribute
System.Runtime.InteropServices.PreserveSigAttribute
System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute
System.Runtime.InteropServices.ProgIdAttribute
System.Runtime.InteropServices.StructLayoutAttribute
System.Runtime.InteropServices.TypeLibFuncAttribute
System.Runtime.InteropServices.TypeLibTypeAttribute
System.Runtime.InteropServices.TypeLibVarAttribute
System.Runtime.InteropServices.TypeLibVersionAttribute
System.Runtime.Remoting.Messaging.OneWayAttribute
System.Runtime.Remoting.Metadata.SoapAttribute
System.Runtime.Remoting.Proxies.ProxyAttribute
System.Security.AllowPartiallyTrustedCallersAttribute
System.Security.Permissions.SecurityAttribute
System.Security.SuppressUnmanagedCodeSecurityAttribute
System.Security.UnverifiableCodeAttribute
System.SerializableAttribute
System.STAThreadAttribute
System.ThreadStaticAttribute
System.Web.Services.Configuration.XmlFormatExtensionAttribute
System.Web.Services.Configuration.XmlFormatExtensionPointAttribute
System.Web.Services.Configuration.XmlFormatExtensionPrefixAttribute
System.Web.Services.Protocols.HttpMethodAttribute
System.Web.Services.Protocols.MatchAttribute
System.Web.Services.Protocols.SoapDocumentMethodAttribute
System.Web.Services.Protocols.SoapDocumentServiceAttribute
System.Web.Services.Protocols.SoapExtensionAttribute
System.Web.Services.Protocols.SoapHeaderAttribute
System.Web.Services.Protocols.SoapRpcMethodAttribute
System.Web.Services.Protocols.SoapRpcServiceAttribute
System.Web.Services.WebMethodAttribute
System.Web.Services.WebServiceAttribute
System.Web.Services.WebServiceBindingAttribute
System.Web.UI.ConstructorNeedsTagAttribute
System.Web.UI.ControlBuilderAttribute
System.Web.UI.DataBindingHandlerAttribute
System.Web.UI.ParseChildrenAttribute
System.Web.UI.PartialCachingAttribute
System.Web.UI.PersistChildrenAttribute
System.Web.UI.PersistenceModeAttribute
System.Web.UI.TagPrefixAttribute
System.Web.UI.TemplateContainerAttribute
System.Web.UI.ToolboxDataAttribute
System.Web.UI.ValidationPropertyAttribute
System.Xml.Serialization.SoapAttributeAttribute
System.Xml.Serialization.SoapElementAttribute
System.Xml.Serialization.SoapEnumAttribute
System.Xml.Serialization.SoapIgnoreAttribute
System.Xml.Serialization.SoapIncludeAttribute
System.Xml.Serialization.SoapTypeAttribute
System.Xml.Serialization.XmlAnyAttributeAttribute
System.Xml.Serialization.XmlAnyElementAttribute
System.Xml.Serialization.XmlArrayAttribute
System.Xml.Serialization.XmlArrayItemAttribute
System.Xml.Serialization.XmlAttributeAttribute
System.Xml.Serialization.XmlChoiceIdentifierAttribute
System.Xml.Serialization.XmlElementAttribute
System.Xml.Serialization.XmlEnumAttribute
System.Xml.Serialization.XmlIgnoreAttribute
System.Xml.Serialization.XmlIncludeAttribute
System.Xml.Serialization.XmlNamespaceDeclarationsAttribute
System.Xml.Serialization.XmlRootAttribute
System.Xml.Serialization.XmlTextAttribute
System.Xml.Serialization.XmlTypeAttribute
System.STAThreadAttribute
大家在一般使用中会留意到这个属性吗?用VS.NET新建一个项目,往往在main前面会如下面所示:
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new frmMain());
}
其实这个就是属性类STAThreadAttribute了,它的作用表示应用程序的COM线程模型是单线程单元(STA)。
属性类的实用性:
1.利用XML相关的属性类,将相关业务类XML序列化,可以达到保存状态和远程传输交换类信息等作用。
共14个和XML相关的属性类:
System.Xml.Serialization.XmlAnyAttributeAttribute
System.Xml.Serialization.XmlAnyElementAttribute
System.Xml.Serialization.XmlArrayAttribute
System.Xml.Serialization.XmlArrayItemAttribute
System.Xml.Serialization.XmlAttributeAttribute
System.Xml.Serialization.XmlChoiceIdentifierAttribute
System.Xml.Serialization.XmlElementAttribute
System.Xml.Serialization.XmlEnumAttribute
System.Xml.Serialization.XmlIgnoreAttribute
System.Xml.Serialization.XmlIncludeAttribute
System.Xml.Serialization.XmlNamespaceDeclarationsAttribute
System.Xml.Serialization.XmlRootAttribute
System.Xml.Serialization.XmlTextAttribute
System.Xml.Serialization.XmlTypeAttribute
最近做一个项目,需要将一些界面输入的有一定结构规律的信息保存起来,然后下次需要时候可以调入到对应的界面位置上使用。(其实这个是很多应用都会碰到的)。结构和UI的对应关系可能会经常变动的,而且结构中需要填写的内容不是所有都必须的,直接用关系型数据库来保存似乎不是太好的方案。首先想到就是用XML文件来保存这些信息了,而界面之间的信息显示是有关联的,可以说需要一个缓冲来记录这些信息,想到的就是定义一个类来记录和操作这些信息。这自然遇到一个问题,如何保持类和XML数据的同步呢?
生成的XML文件需要给其它业务来做处理,格式上有一定的规范,对于类来说,信息都保存在字段或者属性那里的,并没有区别,但XML中可能有些信息是Attribute,有些又是Element的。如何灵活地处理这些关系呢?用与XML相关的属性来定义这些字段和类就可以了。
(1) 类信息序列化到XML文件中的代码
{
XmlSerializer s = new XmlSerializer(typeof(Tables));
TextWriter writer = new StreamWriter(filename);
Tables group = new Tables();
group.GroupID = 10.089f;
group.IsActive = false;
group.HexBytes = new byte[1]{Convert.ToByte(100)};
Employee x = new Employee();
Employee y = new Employee();
x.Name = "Jack";
y.Name = "Jill";
x.des2 = "Yyyy";
x.colType = new ColumnType[2];
x.colType[0] = new ColumnType();
x.colType[1] = new ColumnType();
x.colType[0].linkField = "Haaa";
x.colType[1].linkType = "Zzzz";
y.Age[0] = 20;
y.Age[1] = 40;
y.Desc = "OK";
group.Employees = new Employee[2]{x,y};
Manager mgr = new Manager();
mgr.Name = "Sara";
mgr.Level = 4;
mgr.Desc = "Yes";
mgr.aHead = true;
group.Manager = mgr;
group.ExtraInfo = new ArrayList();
group.ExtraInfo.Add(42);
group.ExtraInfo.Add("Answer");
s.Serialize(writer, group);
writer.Close();
}
{
FileStream fs = new FileStream(filename, FileMode.Open);
XmlSerializer x = new XmlSerializer(typeof(Tables));
Tables g = (Tables) x.Deserialize(fs);
int i=0;
foreach(Employee e in g.Employees)
{
i = i + 1;
Console.WriteLine("No {0} Name: {1}",i.ToString(),e.Name);
}
Console.WriteLine(g.Manager.Name);
Console.WriteLine(g.GroupID);
Console.WriteLine(g.HexBytes[0]);
}
<Tables xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Member>
<Employee AHead="false">
<Name>Jack</Name>
<Age>0</Age>
<Age>0</Age>
<des2>Yyyy</des2>
<ColumnType LinkField="Haaa" />
<ColumnType LinkType="Zzzz" />
</Employee>
<Employee Desc="OK" AHead="false">
<Name>Jill</Name>
<Age>20</Age>
<Age>40</Age>
</Employee>
</Member>
<Building>10.088999748229981</Building>
<HexBytes>64</HexBytes>
<IsActive>false</IsActive>
<Manager Desc="Yes" AHead="true">
<Name>Sara</Name>
<Age>0</Age>
<Age>0</Age>
<Level>4</Level>
</Manager>
<ObjectNumber>42</ObjectNumber>
<ObjectString>Answer</ObjectString>
</Tables>
{
[XmlArray(ElementName = "Member")]
public Employee[] Employees;
[XmlElement(DataType = "double",
ElementName = "Building")]
public double GroupID;
[XmlElement(DataType = "hexBinary")]
public byte [] HexBytes;
[XmlElement(DataType = "boolean")]
public bool IsActive;
[XmlElement(Type = typeof(Manager))]
public Employee Manager;
[XmlElement(typeof(int),
ElementName = "ObjectNumber"),
XmlElement(typeof(string),
ElementName = "ObjectString")]
public ArrayList ExtraInfo;
}
{
public string Name;
[XmlElement(typeof(int))]
public int[] Age = new int[2];
[XmlAttribute(AttributeName = "Desc")]
public string Desc;
[XmlAttribute(AttributeName = "AHead")]
public bool aHead;
public string des2;
[XmlElement(ElementName="ColumnType")]
public ColumnType[] colType;
}
2.自己根据需要定义自己的属性类,例如定义相关业务类和UI的关系。
在使用中,信息不是一个UI就完成的,可能经过了几个UI,或者几个页面去交互,但可能业务的调整,显示的位置或者一些参数可能需要调整的,这些UI的信息能否也定义为类的某些属性?
从.NET的Attribute派生一个客户定制类可以轻松做到这点,定制类只需要从System.Attribute派生即可。
public class LayoutAttribute : Attribute
{
string m_desc;
public string OwnPage;
public string GetDesc()
{
return m_desc;
}
public LayoutAttribute(string strDesc)
{
m_desc = strDesc;
}
}
AttributeUsage这个类定义了LayoutAttribute的一些基本信息,例如这里定义了LayoutAttribute适用于字段,类,并且允许重复定义的。
在应用中,可以利用反射机制,将这些定义的信息获取,从而判断应该在界面上如何处理了。
Console.WriteLine(myType.FullName);
FieldInfo myFieldInfo = myType.GetField("Level");
object[] atts = myFieldInfo.GetCustomAttributes(false);
for (int i=0;i<atts.Length;i++)
Console.WriteLine(((LayoutAttribute)atts[i]).OwnPage);
例子运行结果:(同时在当前目录下生成testXmlAttr.xml)
例子代码