Signum Framework Logo
"Open framework that encourages convention over configuration, using C# code,
not XML files, to model at the right level of abstraction and achieve deadlines.
...but also has a full Linq provider, and syncs the schema for you!"
Login
RSS

Search

»



Main
Index
Map
Videos
Download
Source code
Tutorials
Forum
FAQ



Image



PoweredBy

Description Attributes

RSS
Modified on 2010/01/04 06:03 by olmo Categorized as SignumUtilities

Descriptions Introducction

As applications get bigger is more difficult to keep all the names consistent (entity names, query names, property names...). Specially with the advent of Signum.Web, a lot of redundancy appears.

Description infrastructure has been included in Signum Framework 2.0

Description Attributes allow to put a user-friendly name over your types, properties and enums, so it can be used by the framework in many different scenarios. Examples:

  • Windows and Web:
    • Titles (NormalWindows, AdminWindow, SearchWindow)
    • EntityControls labels and enum combo boxes
    • SearchControls columns and filters
    • MainMenu (AdminOptions and ExploreOptions)
    • Error messages from Signum Framework (i.e: Validation)

  • Future (Signum.Extensions)
    • Operations?
    • Reports?
    • Authorization Menus?
    • Help?

In order to do so, it provides different features:
  1. NiceName: Simple description for types, enums and properties.
  2. NicePluralName : Plural description for types only, necessary for MainMenu, SearchControl, some error messages....
  3. GetGender & GenderAwareResource: Gender detection for types only, necessary for some error messages and help in the future (not necessary in English)
  4. Localization

public static class DescriptionManager
{
   public static Func<Type, string> CleanTypeName = t => t.Name; //To allow MyEntityDN -> MyEntity
   public static Func<Type, Type> CleanType = t => t; //To allow Lite<T> -> T

public static string NiceToString(this Enum a) public static string NiceName(this Type type) public static string NiceName(this PropertyInfo pi) public static bool IsDefaultName(this PropertyInfo pi) //Returns true if the name of the property is the same that the CleanName of the property type

public static string NicePluralName(this Type type

public static Gender GetGender(this Type type) public static string GetGenderAwareResource(this ResourceManager resource, string resourceKey, Gender gender) public static string GetGenderAwareResource(this Type type, Expression<Func<string>> resource) }

Fortunately, most of the work can be done automatically. NiceName is just the name of the type, enum or property after doing SpacePascal or splitting by underscore. For accuracy, it's is also able to clean 'hungarian' notations on your types (DN postfix, cls prefix) though the public static delegate CleanType, and is able to propagate overridden descriptions of types to properties for properties with default name.

Also, NaturalLanguageTool is able to infer the plural description and the gender from a the NiceName. We will see more about this class at the end of the page.

However, you always have the option to override the automatic behavior, in order to do so there are two models for description: Hard-coded and Resource-based.

Hard-coded

Using attributes with the text over the entities itself to override the default behavior:

  • NiceName using System.ComponentModel.DescriptionAttribute (.Net Framework).
  • PluralNiceName using PluralDescriptionAttribute.
  • Gender using GenderAttribute.

public class DescriptionAttribute : Attribute
{
    public virtual string Description { get; }
    public DescriptionAttribute(string description);
}

[AttributeUsage(AttributeTargets.Class)] public class PluralDescriptionAttribute : Attribute { public string PluralDescription { get; private set; } public PluralDescriptionAttribute(string pluralDescription) }

[AttributeUsage(AttributeTargets.Class)] public class GenderAttribute : Attribute { public Gender Gender { get; private set; } public GenderAttribute(Gender gender) }

Example in a English-only application:

[PluralDescription("People")]
public class PersonDN : Entity
{
   [Description("1st Name")] //Cos 1stName is not a valid C# identifier
   public FirstName { get{...} set{..}}
   public LastName { get{...} set{..}}
}

Or in a Spanish-only application:

[Gender(Gender.Femenine)] //The SpanishGenderDetector will think that a word that ends by 'e' is masculine
public class SedeDN: Entity
{
}

Resource-based

As you see, Localization is orthogonal to NiceName, PluralNiceName and Gender. If you translate an application (or module) to Spanish, you will need to change the descriptions of your entities, enums and properties. You will also need to change the plural version of your entities, and the fact that a name is masculine, feminine or neutral (i.e: german) also changes from language to language. The natural place to put this information is on satellite assemblies of resources.

Once you place a LocalizeDescriptionsAttribute at the assembly level (AssemblyInfo.cs), whenever you call NiceName, NicePluralName or GetGender DescriptionManager will look at the resources of the satellite assembly first.

[AttributeUsage(AttributeTargets.Assembly)]
public class LocalizeDescriptionsAttribute : Attribute
{
}

The keys of the resources have to follow some rules:

  • NiceName: Use "MyType" for a type. "MyType_MyProperty" for a property and "MyEnum_EnumValue" for an enum.
  • PluralNiceName: Use "MyType_Plural" for a Type.
  • Gender using GenderAttribute: Use "MyType_Gender" and use "m" (for Masculine), "f" (for Feminine) and "n" (for Neuter).

So an Example for this code in English:

public class PersonDN : Entity
{
   public FirstName { get{...} set{..}}
   public LastName { get{...} set{..}}
}

would be this Spanish resources:

KeyValue
PersonDNPersona
PersonDN_PluralPersonas
PersonDN_Genderf
PersonDN_FirstNameNombre
PersonDN_LastNameApellido

Fortunately, PersonDN_Plural and PersonDN_Gender can be inferred by NaturalLanguageTools once you change PersonDN to Persona.

Note that you can also mix Resources and Attributes, but if the assembly is marked with LocalizeDescriptionsAttribute, resources will take priority, otherwise resources will be ignored.

The algorithm is represented in the following diagram.

Image

NaturalLanguageTools

Most of the logic that is able to infer the plural form of a singular text, or the gender of a name is found in this class.

The class itself doesn't do a lot of work, instead it serves as a repository for language-specific IPluralizer and IGenderDetector

public static class NaturalLanguageTools
{
   public static Dictionary<string, IPluralizer> Pluralizers = new Dictionary<string, IPluralizer>
   {
       {"es", new SpanishPluralizer()},
       {"en", new EnglishPluralizer()},
   };

public static Dictionary<string, IGenderDetector> GenderDetectors = new Dictionary<string, IGenderDetector> { {"es", new SpanishGenderDetector()}, };

public static Gender GetGender(string name); public static string Pluralize(string singularName); }

public interface IPluralizer { string MakePlural(string singularName); }

public interface IGenderDetector { Gender GetGender(string name); }

If your speak a different language maybe is good to take a look at the current ones and write your own pluralizer/gender detector with some heuristics. You will never get it perfect but it's easy to save you 80% of the work.
Creative Commons License Signum Framework Site by Signum Software is licensed under a Creative Commons Attribution 3.0 License.
Powered by ScrewTurn Wiki version 3.0.5.600.