Esta ‘pequeña feature’ era algo que tenía en mente hacer desde hace tiempo, después de otros pull request con features y pequeños arreglos, he podido sacar un rato y realizar la implementación del mismo como podéis ver en este change set. La idea es básicamente poder tunear el servicio que se encarga de realizar la singularización y pluralización de nuestras entidades, por ejemplo para decidir por convención el nombre de una tabla. En realidad, este servicio es utilizado principalmente por PluralizingTableNameConvention y PluralizingEntitySetNameConvention para realizar su trabajo. Hasta ahora, es clase no era pública y su uso estaba fijado por las convenciones anteriores, no teniendo ninguna forma de cambiar la implementación del mismo. A lo largo de las siguientes líneas os contaré los cambios realizados y lo que podremos hacer en la siguiente versión de EF.
Haciendo el servicio público
Lo primero es crear el contrato para este servicio, que como podéis ver a continuación es tan sencillo como lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<span class="kwrd">public</span> <span class="kwrd">interface</span> IPluralizationService { <span class="rem">/// <summary></span> <span class="rem">/// Check if a word is plural.</span> <span class="rem">/// </summary></span> <span class="rem">/// <param name="word">The word to check.</param></span> <span class="rem">/// <returns>True if word is plural; false otherwise..</returns></span> <span class="kwrd">bool</span> IsPlural(<span class="kwrd">string</span> word); <span class="rem">/// <summary></span> <span class="rem">/// Check if a word is singular.</span> <span class="rem">/// </summary></span> <span class="rem">/// <param name="word">The word to check.</param></span> <span class="rem">/// <returns>True if word is singular; false otherwise.</returns></span> <span class="kwrd">bool</span> IsSingular(<span class="kwrd">string</span> word); <span class="rem">/// <summary></span> <span class="rem">/// Pluralize a word using the service.</span> <span class="rem">/// </summary></span> <span class="rem">/// <param name="word">The word to pluralize.</param></span> <span class="rem">/// <returns>The pluralized word </returns></span> <span class="kwrd">string</span> Pluralize(<span class="kwrd">string</span> word); <span class="rem">/// <summary></span> <span class="rem">/// Singularize a word using the service.</span> <span class="rem">/// </summary></span> <span class="rem">/// <param name="word">The word to singularize.</param></span> <span class="rem">/// <returns>The singularized word.</returns></span> <span class="kwrd">string</span> Singularize(<span class="kwrd">string</span> word); } |
Este servicio, por defecto, tendrá una implementación basada en lengua inglesa, llamado EnglishPluralizationService, que no es más que la adaptación a este contrato del servicio anterior, por compatibilidad. Para registrar la implementación que queramos usar se ha incluido un nuevo método en DbConfiguration llamado SetPluralizationService, gracias al cuál podremos establecer esta implementación, si es que queremos cambiar la existente. A continuación podemos ver un ejemplo de esto:
1 2 3 4 5 6 7 8 |
<span class="kwrd">public</span> <span class="kwrd">class</span> OrderContextDbConfiguration : DbConfiguration { <span class="kwrd">public</span> OrderContextDbConfiguration() { SetPluralizationService(<span class="kwrd">new</span> SpanishPluralizationService()); } } |
Un pequeño añadido aprovechando la coyuntura..
Ya metidos en faena, hay una pequeña cosa que podíamos hacer para no obligar a nadie a crear un servicio de pluralización si alguna de las reglas del existente no le convenía o quisiera ‘customizar’ este trabajo. La idea es básicamente permitir al usuario incluir en el servicio de pluralización la definición de una entrada de diccionario, con los correspondientes Singular y Plural, como podemos ver en el siguiente fragmento.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<span class="kwrd">public</span> <span class="kwrd">class</span> CustomPluralizationEntry { <span class="rem">/// <summary></span> <span class="rem">/// Get the singular.</span> <span class="rem">/// </summary></span> <span class="kwrd">public</span> <span class="kwrd">string</span> Singular { get; <span class="kwrd">private</span> set; } <span class="rem">/// <summary></span> <span class="rem">/// Get the plural.</span> <span class="rem">/// </summary></span> <span class="kwrd">public</span> <span class="kwrd">string</span> Plural { get; <span class="kwrd">private</span> set; } <span class="rem">/// <summary></span> <span class="rem">/// Create a new instance</span> <span class="rem">/// </summary></span> <span class="rem">/// <param name="singular">A non null or empty string representing the singular.</param></span> <span class="rem">/// <param name="plural">A non null or empty string representing the plural.</param></span> <span class="kwrd">public</span> CustomPluralizationEntry(<span class="kwrd">string</span> singular, <span class="kwrd">string</span> plural) { Check.NotEmpty(singular, <span class="str">"singular"</span>); Check.NotEmpty(plural, <span class="str">"plural"</span>); Singular = singular; Plural = plural; } } |
Estas entradas de diccionario se pueden establecer en el constructor del servicio de pluralización antes de registrarlo, por ejemplo, ahora utilizando un IDbDependencyResolver, como vemos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<span class="kwrd">public</span> <span class="kwrd">class</span> UnityDependencyResolver : IDbDependencyResolver { IUnityContainer _container; <span class="kwrd">public</span> UnityDependencyResolver() { _container = <span class="kwrd">new</span> UnityContainer(); _container.RegisterType<IPluralizationService>(<span class="kwrd">new</span> InjectionFactory((c) => { var pluralizationService = <span class="kwrd">new</span> EnglishPluralizationService(<span class="kwrd">new</span> CustomPluralizationEntry[] { <span class="kwrd">new</span> CustomPluralizationEntry(<span class="str">"Producto"</span>,<span class="str">"Productos"</span>) }); <span class="kwrd">return</span> pluralizationService; })); } <span class="kwrd">public</span> <span class="kwrd">object</span> GetService(Type type, <span class="kwrd">object</span> key) { <span class="kwrd">if</span> (_container.IsRegistered(type)) <span class="kwrd">return</span> _container.Resolve(type, (<span class="kwrd">string</span>)key); <span class="kwrd">return</span> <span class="kwrd">null</span>; } } |
Bonus
Bien, una vez hecho público el servicio lo mejor era dar un ejemplo de implementación, por eso, otra de las cosas que he estado haciendo estas vacaciones ha sido la creación de este servicio de pluralización en castellano, aunque por ahora no lo he hecho público puesto que estoy mirando la mejor manera de hacerlo…en cuanto esté os comentaré como podréis utilizarlo….
Espero que os gustara la entrada y, como no, os invito a pasaros por el la página del proyecto en CodePlex y a contribuir de las muchas formas en las que se puede…
Saludos
Unai
Desde hace ya un tiempo vengo recibiendo bastantes correos con respecto a una de las nuevas características