En el post anterior sobre convenciones en EF 4 + CTP 5 introdujimos al lector en el significado de las convenciones y como obtener y manejar la lista de las mismas presente de forma automática. A mayores, también expusimos los distintos contratos y clases base con las que las convenciones han sido creadas. De todos estos contratos base, en esta CTP, solamente tenemos uno de forma pública, es decir, solamente uno de estos contratos es el que debemos usar para crear nuestras propias convenciones.
Este contrato es AttributeConfigurationConvention, y tiene como firma principal de su clase lo siguiente:
1 2 3 4 5 6 7 8 |
<span class="kwrd">public</span> <span class="kwrd">abstract</span> <span class="kwrd">class</span> AttributeConfigurationConvention<TMemberInfo, TConfiguration, TAttribute> : IConfigurationConvention<TMemberInfo, TConfiguration>, IConvention <span class="kwrd">where</span> TMemberInfo: MemberInfo <span class="kwrd">where</span> TConfiguration: ConfigurationBase <span class="kwrd">where</span> TAttribute: Attribute { } |
Como se puede observar en esta firma, hay varios elementos fundamentales que nos permite expresar como va a ser nuestra convención y a que se va a aplicar. En primer lugar, el parámetro genérico TMemberInfo nos permitirá especificar a que tipo de elemento se aplica la convención, de tal forma que si este parámetro fuera un PropertyInfo la convención sería para alguna de las propiedades de una entidad y si fuera por ejemplo Type sería una convención relativa a la entidad en si misma, el nombre de la tabla po ejemplo. El segundo de los parámetros genéricos, TConfiguration, se refiere a los distintos elementos de configuración que podemos aplicar, los contenidos dentro de la jerarquía de ConfigurationBase. Lógicamente puede ver toda la jerarquía con cualquier herramienta de reflexión, aquí exponemos algunos elementos interesantes que están contenidos dentro de la misma: StringPropertyConfiguration, DecimalPropertyConfiguration,ForeignKeyConstraintConfiguration, EntityTypeConfiguration.
El último de los elementos del genérico es TAttribute, cuya una restricción es que sea un Atributo.En realidad, este elemento está aquí para permitirnos asociar una convención a un atributo con el que podamos decorar nuestras clases. Fíjese que aquí es dónde entra una de las features que más llama la atención de esta y anteriores CTP que no es más ni menos que la integración con DataAnnotations. Esta integración con Data Annotations no es más que el soporte de los diferentes atributos que definen dentro de las convenciones, así, si en Data Annotations tenemos un atributo MaxLength entonces tendremos una convención que hará uso de este atributo, a continuación se muestra el código de una posible convención haciendo uso de este atributo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span class="kwrd">public</span> <span class="kwrd">class</span> CustomMaxLengthAttributeConvention :AttributeConfigurationConvention<PropertyInfo,LengthPropertyConfiguration,MaxLengthAttribute> { <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Apply(PropertyInfo memberInfo, LengthPropertyConfiguration configuration, MaxLengthAttribute attribute) { <span class="kwrd">if</span> ((attribute.Length == 0) || (attribute.Length < -1)) { <span class="rem">//TODO: throw error here!</span> } <span class="kwrd">if</span> (!configuration.IsMaxLength.HasValue && !configuration.MaxLength.HasValue) { <span class="kwrd">if</span> (attribute.Length == -1) { configuration.IsMaxLength = <span class="kwrd">true</span>; } <span class="kwrd">else</span> { configuration.MaxLength = <span class="kwrd">new</span> <span class="kwrd">int</span>?(attribute.Length); } } } } |
Por supuesto, para ciertas convenciones necesarias no hay un atributo dentro de Data Annotations que nos permita hacer una similitud, como podría ser MaxLength, para estos casos, EntityFramework.dll, librería de esta CTP 5, extiende el conjunto de atributos de este namespace. Un ejemplo de ello pueden ser los atributos TableAttribute o ColumnAttribute.
Con esto acaba esta segunda entrega, en la siguiente, trataremos de explicar paso a paso los pasos para implementar una nueva convención, esta convención, trataremos que además de fines formativos sirva también en la vida real…..
Saludos
Unai
El tema de las convenciones personalizadas para el modelo de Code First sin duda ha sido una de las cosas