|
using System.ComponentModel.DataAnnotations.Resources;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace System.ComponentModel.DataAnnotations {
/// <summary>
/// DisplayAttribute is a general-purpose attribute to specify user-visible globalizable strings for types and members.
/// The string properties of this class can be used either as literals or as resource identifiers into a specified
/// <see cref="ResourceType"/>
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = false)]
public sealed class DisplayAttribute : Attribute {
#region Member Fields
private Type _resourceType;
private LocalizableString _shortName = new LocalizableString("ShortName");
private LocalizableString _name = new LocalizableString("Name");
private LocalizableString _description = new LocalizableString("Description");
private LocalizableString _prompt = new LocalizableString("Prompt");
private LocalizableString _groupName = new LocalizableString("GroupName");
private bool? _autoGenerateField;
private bool? _autoGenerateFilter;
private int? _order;
#endregion
#region All Constructors
/// <summary>
/// Default constructor for DisplayAttribute. All associated string properties and methods will return <c>null</c>.
/// </summary>
public DisplayAttribute() {
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the ShortName attribute property, which may be a resource key string.
/// <para>
/// Consumers must use the <see cref="GetShortName"/> method to retrieve the UI display string.
/// </para>
/// </summary>
/// <remarks>
/// The property contains either the literal, non-localized string or the resource key
/// to be used in conjunction with <see cref="ResourceType"/> to configure a localized
/// short name for display.
/// <para>
/// The <see cref="GetShortName"/> method will return either the literal, non-localized
/// string or the localized string when <see cref="ResourceType"/> has been specified.
/// </para>
/// </remarks>
/// <value>
/// The short name is generally used as the grid column label for a UI element bound to the member
/// bearing this attribute. A <c>null</c> or empty string is legal, and consumers must allow for that.
/// </value>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The property and method are a matched pair")]
public string ShortName {
get {
return this._shortName.Value;
}
set {
if (this._shortName.Value != value) {
this._shortName.Value = value;
}
}
}
/// <summary>
/// Gets or sets the Name attribute property, which may be a resource key string.
/// <para>
/// Consumers must use the <see cref="GetName"/> method to retrieve the UI display string.
/// </para>
/// </summary>
/// <remarks>
/// The property contains either the literal, non-localized string or the resource key
/// to be used in conjunction with <see cref="ResourceType"/> to configure a localized
/// name for display.
/// <para>
/// The <see cref="GetName"/> method will return either the literal, non-localized
/// string or the localized string when <see cref="ResourceType"/> has been specified.
/// </para>
/// </remarks>
/// <value>
/// The name is generally used as the field label for a UI element bound to the member
/// bearing this attribute. A <c>null</c> or empty string is legal, and consumers must allow for that.
/// </value>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The property and method are a matched pair")]
public string Name {
get {
return this._name.Value;
}
set {
if (this._name.Value != value) {
this._name.Value = value;
}
}
}
/// <summary>
/// Gets or sets the Description attribute property, which may be a resource key string.
/// <para>
/// Consumers must use the <see cref="GetDescription"/> method to retrieve the UI display string.
/// </para>
/// </summary>
/// <remarks>
/// The property contains either the literal, non-localized string or the resource key
/// to be used in conjunction with <see cref="ResourceType"/> to configure a localized
/// description for display.
/// <para>
/// The <see cref="GetDescription"/> method will return either the literal, non-localized
/// string or the localized string when <see cref="ResourceType"/> has been specified.
/// </para>
/// </remarks>
/// <value>
/// Description is generally used as a tool tip or description a UI element bound to the member
/// bearing this attribute. A <c>null</c> or empty string is legal, and consumers must allow for that.
/// </value>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The property and method are a matched pair")]
public string Description {
get {
return this._description.Value;
}
set {
if (this._description.Value != value) {
this._description.Value = value;
}
}
}
/// <summary>
/// Gets or sets the Prompt attribute property, which may be a resource key string.
/// <para>
/// Consumers must use the <see cref="GetPrompt"/> method to retrieve the UI display string.
/// </para>
/// </summary>
/// <remarks>
/// The property contains either the literal, non-localized string or the resource key
/// to be used in conjunction with <see cref="ResourceType"/> to configure a localized
/// prompt for display.
/// <para>
/// The <see cref="GetPrompt"/> method will return either the literal, non-localized
/// string or the localized string when <see cref="ResourceType"/> has been specified.
/// </para>
/// </remarks>
/// <value>
/// A prompt is generally used as a prompt or watermark for a UI element bound to the member
/// bearing this attribute. A <c>null</c> or empty string is legal, and consumers must allow for that.
/// </value>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The property and method are a matched pair")]
public string Prompt {
get {
return this._prompt.Value;
}
set {
if (this._prompt.Value != value) {
this._prompt.Value = value;
}
}
}
/// <summary>
/// Gets or sets the GroupName attribute property, which may be a resource key string.
/// <para>
/// Consumers must use the <see cref="GetGroupName"/> method to retrieve the UI display string.
/// </para>
/// </summary>
/// <remarks>
/// The property contains either the literal, non-localized string or the resource key
/// to be used in conjunction with <see cref="ResourceType"/> to configure a localized
/// group name for display.
/// <para>
/// The <see cref="GetGroupName"/> method will return either the literal, non-localized
/// string or the localized string when <see cref="ResourceType"/> has been specified.
/// </para>
/// </remarks>
/// <value>
/// A group name is used for grouping fields into the UI. A <c>null</c> or empty string is legal,
/// and consumers must allow for that.
/// </value>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The property and method are a matched pair")]
public string GroupName {
get {
return this._groupName.Value;
}
set {
if (this._groupName.Value != value) {
this._groupName.Value = value;
}
}
}
/// <summary>
/// Gets or sets the <see cref="System.Type"/> that contains the resources for <see cref="ShortName"/>,
/// <see cref="Name"/>, <see cref="Description"/>, <see cref="Prompt"/>, and <see cref="GroupName"/>.
/// Using <see cref="ResourceType"/> along with these Key properties, allows the <see cref="GetShortName"/>,
/// <see cref="GetName"/>, <see cref="GetDescription"/>, <see cref="GetPrompt"/>, and <see cref="GetGroupName"/>
/// methods to return localized values.
/// </summary>
public Type ResourceType {
get {
return this._resourceType;
}
set {
if (this._resourceType != value) {
this._resourceType = value;
this._shortName.ResourceType = value;
this._name.ResourceType = value;
this._description.ResourceType = value;
this._prompt.ResourceType = value;
this._groupName.ResourceType = value;
}
}
}
/// <summary>
/// Gets or sets whether UI should be generated automatically to display this field. If this property is not
/// set then the presentation layer will automatically determine whether UI should be generated. Setting this
/// property allows an override of the default behavior of the presentation layer.
/// <para>
/// Consumers must use the <see cref="GetAutoGenerateField"/> method to retrieve the value, as this property getter will throw
/// an exception if the value has not been set.
/// </para>
/// </summary>
/// <exception cref="System.InvalidOperationException">
/// If the getter of this property is invoked when the value has not been explicitly set using the setter.
/// </exception>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The property and method are a matched pair")]
public bool AutoGenerateField {
get {
if (!this._autoGenerateField.HasValue) {
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, DataAnnotationsResources.DisplayAttribute_PropertyNotSet, "AutoGenerateField", "GetAutoGenerateField"));
}
return this._autoGenerateField.Value;
}
set {
this._autoGenerateField = value;
}
}
/// <summary>
/// Gets or sets whether UI should be generated automatically to display filtering for this field. If this property is not
/// set then the presentation layer will automatically determine whether filtering UI should be generated. Setting this
/// property allows an override of the default behavior of the presentation layer.
/// <para>
/// Consumers must use the <see cref="GetAutoGenerateFilter"/> method to retrieve the value, as this property getter will throw
/// an exception if the value has not been set.
/// </para>
/// </summary>
/// <exception cref="System.InvalidOperationException">
/// If the getter of this property is invoked when the value has not been explicitly set using the setter.
/// </exception>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The property and method are a matched pair")]
public bool AutoGenerateFilter {
get {
if (!this._autoGenerateFilter.HasValue) {
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, DataAnnotationsResources.DisplayAttribute_PropertyNotSet, "AutoGenerateFilter", "GetAutoGenerateFilter"));
}
return this._autoGenerateFilter.Value;
}
set {
this._autoGenerateFilter = value;
}
}
/// <summary>
/// Gets or sets the order in which this field should be displayed. If this property is not set then
/// the presentation layer will automatically determine the order. Setting this property explicitly
/// allows an override of the default behavior of the presentation layer.
/// <para>
/// Consumers must use the <see cref="GetOrder"/> method to retrieve the value, as this property getter will throw
/// an exception if the value has not been set.
/// </para>
/// </summary>
/// <exception cref="System.InvalidOperationException">
/// If the getter of this property is invoked when the value has not been explicitly set using the setter.
/// </exception>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The property and method are a matched pair")]
public int Order {
get {
if (!this._order.HasValue) {
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, DataAnnotationsResources.DisplayAttribute_PropertyNotSet, "Order", "GetOrder"));
}
return this._order.Value;
}
set {
this._order = value;
}
}
#endregion
#region Methods
/// <summary>
/// Gets the UI display string for ShortName.
/// <para>
/// This can be either a literal, non-localized string provided to <see cref="ShortName"/> or the
/// localized string found when <see cref="ResourceType"/> has been specified and <see cref="ShortName"/>
/// represents a resource key within that resource type.
/// </para>
/// </summary>
/// <returns>
/// When <see cref="ResourceType"/> has not been specified, the value of
/// <see cref="ShortName"/> will be returned.
/// <para>
/// When <see cref="ResourceType"/> has been specified and <see cref="ShortName"/>
/// represents a resource key within that resource type, then the localized value will be returned.
/// </para>
/// <para>
/// If <see cref="ShortName"/> is <c>null</c>, the value from <see cref="GetName"/> will be returned.
/// </para>
/// </returns>
/// <exception cref="System.InvalidOperationException">
/// After setting both the <see cref="ResourceType"/> property and the <see cref="ShortName"/> property,
/// but a public static property with a name matching the <see cref="ShortName"/> value couldn't be found
/// on the <see cref="ResourceType"/>.
/// </exception>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does work using a property of the same name")]
public string GetShortName() {
return this._shortName.GetLocalizableValue() ?? this.GetName();
}
/// <summary>
/// Gets the UI display string for Name.
/// <para>
/// This can be either a literal, non-localized string provided to <see cref="Name"/> or the
/// localized string found when <see cref="ResourceType"/> has been specified and <see cref="Name"/>
/// represents a resource key within that resource type.
/// </para>
/// </summary>
/// <returns>
/// When <see cref="ResourceType"/> has not been specified, the value of
/// <see cref="Name"/> will be returned.
/// <para>
/// When <see cref="ResourceType"/> has been specified and <see cref="Name"/>
/// represents a resource key within that resource type, then the localized value will be returned.
/// </para>
/// <para>
/// Can return <c>null</c> and will not fall back onto other values, as it's more likely for the
/// consumer to want to fall back onto the property name.
/// </para>
/// </returns>
/// <exception cref="System.InvalidOperationException">
/// After setting both the <see cref="ResourceType"/> property and the <see cref="Name"/> property,
/// but a public static property with a name matching the <see cref="Name"/> value couldn't be found
/// on the <see cref="ResourceType"/>.
/// </exception>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does work using a property of the same name")]
public string GetName() {
return this._name.GetLocalizableValue();
}
/// <summary>
/// Gets the UI display string for Description.
/// <para>
/// This can be either a literal, non-localized string provided to <see cref="Description"/> or the
/// localized string found when <see cref="ResourceType"/> has been specified and <see cref="Description"/>
/// represents a resource key within that resource type.
/// </para>
/// </summary>
/// <returns>
/// When <see cref="ResourceType"/> has not been specified, the value of
/// <see cref="Description"/> will be returned.
/// <para>
/// When <see cref="ResourceType"/> has been specified and <see cref="Description"/>
/// represents a resource key within that resource type, then the localized value will be returned.
/// </para>
/// </returns>
/// <exception cref="System.InvalidOperationException">
/// After setting both the <see cref="ResourceType"/> property and the <see cref="Description"/> property,
/// but a public static property with a name matching the <see cref="Description"/> value couldn't be found
/// on the <see cref="ResourceType"/>.
/// </exception>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does work using a property of the same name")]
public string GetDescription() {
return this._description.GetLocalizableValue();
}
/// <summary>
/// Gets the UI display string for Prompt.
/// <para>
/// This can be either a literal, non-localized string provided to <see cref="Prompt"/> or the
/// localized string found when <see cref="ResourceType"/> has been specified and <see cref="Prompt"/>
/// represents a resource key within that resource type.
/// </para>
/// </summary>
/// <returns>
/// When <see cref="ResourceType"/> has not been specified, the value of
/// <see cref="Prompt"/> will be returned.
/// <para>
/// When <see cref="ResourceType"/> has been specified and <see cref="Prompt"/>
/// represents a resource key within that resource type, then the localized value will be returned.
/// </para>
/// </returns>
/// <exception cref="System.InvalidOperationException">
/// After setting both the <see cref="ResourceType"/> property and the <see cref="Prompt"/> property,
/// but a public static property with a name matching the <see cref="Prompt"/> value couldn't be found
/// on the <see cref="ResourceType"/>.
/// </exception>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does work using a property of the same name")]
public string GetPrompt() {
return this._prompt.GetLocalizableValue();
}
/// <summary>
/// Gets the UI display string for GroupName.
/// <para>
/// This can be either a literal, non-localized string provided to <see cref="GroupName"/> or the
/// localized string found when <see cref="ResourceType"/> has been specified and <see cref="GroupName"/>
/// represents a resource key within that resource type.
/// </para>
/// </summary>
/// <returns>
/// When <see cref="ResourceType"/> has not been specified, the value of
/// <see cref="GroupName"/> will be returned.
/// <para>
/// When <see cref="ResourceType"/> has been specified and <see cref="GroupName"/>
/// represents a resource key within that resource type, then the localized value will be returned.
/// </para>
/// </returns>
/// <exception cref="System.InvalidOperationException">
/// After setting both the <see cref="ResourceType"/> property and the <see cref="GroupName"/> property,
/// but a public static property with a name matching the <see cref="GroupName"/> value couldn't be found
/// on the <see cref="ResourceType"/>.
/// </exception>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does work using a property of the same name")]
public string GetGroupName() {
return this._groupName.GetLocalizableValue();
}
/// <summary>
/// Gets the value of <see cref="AutoGenerateField"/> if it has been set, or <c>null</c>.
/// </summary>
/// <returns>
/// When <see cref="AutoGenerateField"/> has been set returns the value of that property.
/// <para>
/// When <see cref="AutoGenerateField"/> has not been set returns <c>null</c>.
/// </para>
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does work using a property of the same name")]
public bool? GetAutoGenerateField() {
return this._autoGenerateField;
}
/// <summary>
/// Gets the value of <see cref="AutoGenerateFilter"/> if it has been set, or <c>null</c>.
/// </summary>
/// <returns>
/// When <see cref="AutoGenerateFilter"/> has been set returns the value of that property.
/// <para>
/// When <see cref="AutoGenerateFilter"/> has not been set returns <c>null</c>.
/// </para>
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does work using a property of the same name")]
public bool? GetAutoGenerateFilter() {
return this._autoGenerateFilter;
}
/// <summary>
/// Gets the value of <see cref="Order"/> if it has been set, or <c>null</c>.
/// </summary>
/// <returns>
/// When <see cref="Order"/> has been set returns the value of that property.
/// <para>
/// When <see cref="Order"/> has not been set returns <c>null</c>.
/// </para>
/// </returns>
/// <remarks>
/// When an order is not specified, presentation layers should consider using the value
/// of 10000. This value allows for explicitly-ordered fields to be displayed before
/// and after the fields that don't specify an order.
/// </remarks>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does work using a property of the same name")]
public int? GetOrder() {
return this._order;
}
#endregion
}
}
|