开发中灵活使用属性类

什么是属性类?

        从抽象类System.Attribute派生出来的类(无论是直接的还是间接的)都称为属性类(MSDN中的定义)。



        属性类的名称一般都带有Attribute后缀,但使用的时候可以包含也可以忽略,如果你自己起的名字没有这个后缀,则需要全称来区分了。如果不怕输入麻烦,建议还是不管是否有后缀,都输入全称为好,这样可以减少歧义。

        在.NET框架中差不多定义了200个Attribute相关类,可见Attribute的应用十分广泛,它的全图在MSDN中如下:

System.Object
   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>
        
/// 应用程序的主入口点。
        
/// </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文件中的代码

        public void SerializeObject(string filename)
        
{
            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();
        }

(2) XML文件信息变成类的信息的代码
        public void DeserializeObject(string filename)
        
{
            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]);
        }
(3)例子中相关类信息生成的XML文件
<?xml version="1.0" encoding="utf-8"?>
<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>
(4) XML总体框架如何用XML相关属性类描述
    public class 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;
    }
   
(5) 类的字段信息表示为属性的方法
    public class Employee
    
{
        
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派生即可。

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Class,AllowMultiple=true)]
    
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适用于字段,类,并且允许重复定义的。

       在应用中,可以利用反射机制,将这些定义的信息获取,从而判断应该在界面上如何处理了。

            Type myType = Type.GetType("testXmlAttr.Manager");
            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)


例子代码

posted on 2004-09-08 11:59  风前絮~~  阅读(4007)  评论(1编辑  收藏  举报

导航