配置文件,介绍一款好用的基于.NET的配置文件设计工具

在进行框架开发的过程中,我们往往需要对配置文件的结构进行设计,以便产生一套完整的配置方案,供开发人员在使用框架时能对框架进行配置。对于某些大型的框架,其配置节点的结构可能相当复杂,比如某个配置节点(Configuration Element)可以有属性,还可以在其下挂载多个其它的配置节点或者多个配置节点集合(Configuration Element Collection)。如果使用手动编写代码的方式来维护与配置相关的代码,势必会出现大量的重复劳动,比如,需要给每个配置属性添加System.Configuration.ConfigurationPropertyAttribute特性,需要为各个配置节点集合采用相同的代码编写模式(例如重写其中的CreateElement等方法)。这样做不仅耗时而且容易出错。更进一步,Visual Studio支持智能感知技术,如果我们在配置文件编辑器上设置了所要用到的配置信息XSD Schema文件,我们就可以利用智能感知方便快速地编写配置文件。然而,如果我们的配置节点采用手工代码维护,那么在编写完代码之后,还需要另外编写一套XSD Schema文件,以使得开发人员在使用我们的框架时,能够享受到智能感知带来的便捷,这样做不仅工作量大,而且一旦配置信息结构变得复杂,我们就很难确保代码与XSD Schema之间的对应关系。
今天我向大家介绍一款个人觉得比较不错的基于.NET的配置文件设计工具:public class MyAssociatedMetadataTypeTypeDescriptionProvider : AssociatedMetadataTypeTypeDescriptionProvider { public MyAssociatedMetadataTypeTypeDescriptionProvider(Type type) : base(type) { } public MyAssociatedMetadataTypeTypeDescriptionProvider(Type type, Type associatedMetadataType) : base(type, associatedMetadataType) { } private ICustomTypeDescriptor Descriptor { get; set; } public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) { if (null == this.Descriptor) this.Descriptor = new MyCustomTypeDescriptor(base.GetTypeDescriptor(objectType, instance)); return this.Descriptor; } } public class MyCustomTypeDescriptor : CustomTypeDescriptor { public MyCustomTypeDescriptor(ICustomTypeDescriptor wrappedTypeDescriptor) { this.WrappedTypeDescriptor = wrappedTypeDescriptor; } private ICustomTypeDescriptor WrappedTypeDescriptor { get; set; } public override AttributeCollection GetAttributes() { return this.WrappedTypeDescriptor.GetAttributes(); } public override PropertyDescriptorCollection GetProperties() { PropertyDescriptorCollection properties = this.WrappedTypeDescriptor.GetProperties(); List list = new List(); foreach (PropertyDescriptor descriptor in properties) list.Add(new MyPropertyDescriptor(descriptor)); return new PropertyDescriptorCollection(list.ToArray(), true); } public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) { return this.GetProperties(); } } public class MyPropertyDescriptor : PropertyDescriptor { public MyPropertyDescriptor(PropertyDescriptor wrappedPropertyDescriptor) : base(wrappedPropertyDescriptor) { this.WrappedPropertyDescriptor = wrappedPropertyDescriptor; } private PropertyDescriptor WrappedPropertyDescriptor { get; set; } public override void AddValueChanged(object component, EventHandler handler) { this.WrappedPropertyDescriptor.AddValueChanged(component, handler); } public override bool CanResetValue(object component) { return this.WrappedPropertyDescriptor.CanResetValue(component); } public override Type ComponentType { get { return this.WrappedPropertyDescriptor.ComponentType; } } public override bool IsReadOnly { get { return this.WrappedPropertyDescriptor.IsReadOnly; } } public override object GetValue(object component) { return this.WrappedPropertyDescriptor.GetValue(component); } public override Type PropertyType { get { return this.WrappedPropertyDescriptor.PropertyType; } } public override void RemoveValueChanged(object component, EventHandler handler) { this.WrappedPropertyDescriptor.RemoveValueChanged(component, handler); } public override void ResetValue(object component) { this.WrappedPropertyDescriptor.ResetValue(component); } public override void SetValue(object component, object value) { List attributes = new List(); this.FillAttributes(attributes); foreach (Attribute attribute in attributes) { ValidationAttribute validationAttribute = attribute as ValidationAttribute; if (null == validationAttribute) continue; if (!validationAttribute.IsValid(value)) throw new ValidationException(validationAttribute.ErrorMessage, validationAttribute, component); } this.WrappedPropertyDescriptor.SetValue(component, value); } public override bool ShouldSerializeValue(object component) { return this.WrappedPropertyDescriptor.ShouldSerializeValue(component); } public override bool SupportsChangeEvents { get { return this.WrappedPropertyDescriptor.SupportsChangeEvents; } } } // 以下是使用方式: [MetadataType(typeof(ApplicationElementMetadata))] public partial class ApplicationElement { static ApplicationElement() { TypeDescriptor.AddProvider( new MyAssociatedMetadataTypeTypeDescriptionProvider( typeof(ApplicationElement)), typeof(ApplicationElement)); } } public class ApplicationElementMetadata { [Description("Indicates the provider of the Application.")] public string Provider { get; set; } }
然而对于Configuration Section Designer而言,这种繁杂的实现方式已经不复存在。它本身就支持Component Model相关特性的设置,然后会在产生的代码中添加相应的特性描述,大大减轻了开发者的负担。
imageimageimageimageimage介绍一款好用的基于.NET的配置文件设计工具配置文件
产生的代码如下:
imageimageimageimageimageimage介绍一款好用的基于.NET的配置文件设计工具配置文件
Configuration Section Designer应该还有很多不错的功能,时间关系我也没有进行深入研究,有兴趣的朋友不妨下载一个Configuration Section Designer体验一下。
Tags: 

延伸阅读

最新评论

发表评论