2011-10-27 19 views
6

Come ho capito, LLBLGen Pro non può generare POCO sulle proprie entità (vedi qui: http://www.llblgen.com/Pages/featuresLLBLGenPro.aspx).T4 per la generazione di POCO su entità LLBLGen Pro?

Qualcuno ha scritto un T4 che genererà le classi POCO corrispondenti alle entità LLBLGen Pro e genererà la logica di trasformazione appropriata per andare da e verso un'entità e POCO? Qualcun altro ha ideato una soluzione che non implichi la scrittura manuale di tonnellate di codice di trasformazione?

+0

Anche se non ho creato esattamente ciò che non si desidera creare i modelli T4 in realtà non sarà così difficile se si utilizza lo studio modello che può essere scaricato dal sito llblgen. Ho creato un modello che genererebbe le sp a fare la replica manuale (non chiedere!) E quello che devi fare è molto più semplice. Per la mappatura puoi semplicemente usare AutoMapper. Cosa stai cercando di ottenere avendo POCO? –

+0

Grazie cavernicolo. Ciò che vogliamo ottenere usando i POCO è fuori dalla portata della domanda, ma è una buona domanda a parte. Ragioni a parte, credo fermamente che sia possibile farlo, ma speravo che qualcuno avesse un T4 già creato e pubblicamente disponibile. – jakejgordon

risposta

6

abbiamo generato DTOs da LLBLGen piuttosto che utilizzare T4.

Abbiamo avuto la necessità di creare DTOS da un'entità. Queste non sono tecnicamente pocos perché hanno un metodo ToEntity() e FromEntity(), ma forse questo lavorerà per voi.

Abbiamo creato un'interfaccia IDTO<T> che è stata poi implementata dalle classi DTO (uno per ogni entità). Anziché modificare i modelli di entità, abbiamo aggiunto i metodi DTOExtension per convertire un'entità in un DTO (nonché numerose altre conversioni helper).

Qui ci sono i file di modello che è possibile utilizzare all'interno LLBLGen v2.6. Il modello di progettazione nella versione 3 è molto più facile da usare e puoi convertire gran parte di questo codice per la versione 3, se necessario.

File: entityDTOInterface.template

using System; 
using System.ComponentModel; 
using System.Collections; 
using System.Runtime.Serialization; 

using <[RootNamespace]>.HelperClasses; 
using <[RootNamespace]>.EntityClasses; 

using SD.LLBLGen.Pro.ORMSupportClasses; 

namespace <[RootNamespace]>.DTOClasses 
{ 
    /// <summary> 
    /// DTO interface. 
    /// </summary> 
    public interface IDTO<T> 
    { 
     T ToEntity(T toFill); 
     IDTO<T> FromEntity(T entityInstance, Hashtable seenObjects, Hashtable parents); 
    } 
} 

File: entityDTO.template

using System; 
using System.ComponentModel; 
using System.Collections; 
using System.Runtime.Serialization; 

using <[RootNamespace]>.HelperClasses; 
using <[RootNamespace]>.EntityClasses; 

using SD.LLBLGen.Pro.ORMSupportClasses; 

namespace <[RootNamespace]>.DTOClasses 
{ 
    <[ UserCodeRegion "AdditionalNamespaces" ]> 
    // __LLBLGENPRO_USER_CODE_REGION_START AdditionalNamespaces 
    // __LLBLGENPRO_USER_CODE_REGION_END 
    <[ EndUserCodeRegion ]> 
    /// <summary> 
    /// DTO class for the entity '<[CurrentEntityName]>'. 
    /// </summary> 
    [Serializable] 
    public <[If UsePartialClasses]>partial <[EndIf]>class <[CurrentEntityName]>DTO : <[ If IsSubType ]><[ SuperTypeName ]>DTO, <[ EndIf]>IDTO<<[CurrentEntityName]>Entity><[ UserCodeRegion "AdditionalInterfaces" ]> 
     // __LLBLGENPRO_USER_CODE_REGION_START AdditionalInterfaces 
     // __LLBLGENPRO_USER_CODE_REGION_END 
     <[ EndUserCodeRegion ]> 
    { 
     #region Entity Field Public Properties 

<[Foreach EntityField CrLf]>  /// <summary>Get or set the <[EntityFieldName]> property that maps to the Entity <[CurrentEntityName]></summary> 
     public virtual <[If GenerateAsNullableType]><[TypeOfField]>?<[Else]><[TypeOfField]><[EndIf]> <[EntityFieldName]> { get; set; } 
<[NextForeach]>   
     #endregion 

     #region Related Field Public Properties 

<[ Foreach RelatedEntityField CrLf]>  /// <summary>Get or set the <[MappedFieldNameRelatedField]> property that maps to the Entity <[CurrentEntityName]>'s <[ MappedFieldNameRelation ]>.<[ RelatedEntityFieldName ]></summary> 
     public virtual <[If GenerateAsNullableType]><[TypeOfField]>?<[Else]><[TypeOfField]><[EndIf]> <[ MappedFieldNameRelatedField ]> { get; private set; }<[NextForeach]> 

     #endregion 

     #region Custom Fields 
     <[ UserCodeRegion "CustomFieldCode" ]> 
     // __LLBLGENPRO_USER_CODE_REGION_START CustomFieldCode 
     // __LLBLGENPRO_USER_CODE_REGION_END 
     <[ EndUserCodeRegion ]> 
     #endregion 

     #region Ctors 

     /// <summary> 
     /// CTor 
     /// </summary> 
     public <[CurrentEntityName]>DTO() 
     {   
     } 

     /// <summary> 
     /// CTor which initializes the DTO with values from its corresponding entity 
     /// </summary> 
     /// <param name="entityInstance">The entity instance which holds the values for this DTO</param> 
     public <[CurrentEntityName]>DTO(<[CurrentEntityName]>Entity entityInstance) : this(entityInstance, new Hashtable(), new Hashtable()) { } 

     internal <[CurrentEntityName]>DTO(<[CurrentEntityName]>Entity entityInstance, Hashtable seenObjects, Hashtable parents)<[ If IsSubType ]> : base(entityInstance, seenObjects, parents)<[ EndIf]> 
     { 
      FromEntity(entityInstance, seenObjects, parents); 
     } 

     #endregion 

     /// <summary> 
     /// Creates a <[CurrentEntityName]>DTO object from the given entity. 
     /// </summary> 
     public virtual IDTO<<[CurrentEntityName]>Entity> FromEntity(<[CurrentEntityName]>Entity entityInstance, Hashtable seenObjects, Hashtable parents) 
     { 
      <[ If IsSubType ]>base.FromEntity(entityInstance, seenObjects, parents); 
      <[ EndIf]>seenObjects[entityInstance] = this; 
      parents = new Hashtable(parents); 
      parents.Add(entityInstance, null); 

<[Foreach EntityField CrLf]>   this.<[EntityFieldName]> = entityInstance.<[EntityFieldName]>;<[NextForeach]> 
<[Foreach RelatedEntityField CrLf]>   if (entityInstance.AlreadyFetched<[MappedFieldNameRelation]>) 
       this.<[MappedFieldNameRelatedField]> = entityInstance.<[MappedFieldNameRelatedField]>;<[NextForeach]> 
<[Foreach RelatedEntity OneToMany CrLf]><[If Not MappedFieldRelationIsHidden]>   if (entityInstance.AlreadyFetched<[MappedFieldNameRelation]>) 
       <[MappedFieldNameRelation]> = RelatedArray<<[RelatedEntityName]>DTO, <[RelatedEntityName]>Entity>(entityInstance.<[MappedFieldNameRelation]>, seenObjects, parents);<[EndIf]><[NextForeach]> 
<[Foreach RelatedEntity ManyToMany CrLf]><[If Not MappedFieldRelationIsHidden]>   if (entityInstance.AlreadyFetched<[MappedFieldNameRelation]>) 
       <[MappedFieldNameRelation]> = RelatedArray<<[RelatedEntityName]>DTO, <[RelatedEntityName]>Entity>(entityInstance.<[MappedFieldNameRelation]>, seenObjects, parents);<[EndIf]><[NextForeach]> 
<[Foreach RelatedEntity ManyToOne CrLf]><[If Not MappedFieldRelationIsHidden]>   if (entityInstance.AlreadyFetched<[MappedFieldNameRelation]>) 
       <[MappedFieldNameRelation]> = RelatedObject<<[RelatedEntityName]>DTO, <[RelatedEntityName]>Entity>(entityInstance.<[MappedFieldNameRelation]>, seenObjects, parents);//(new <[RelatedEntityName]>DTO(entityInstance.<[MappedFieldNameRelation]>, seenObjects);<[EndIf]><[NextForeach]> 
<[Foreach RelatedEntity OneToOne CrLf]><[If Not MappedFieldRelationIsHidden]>   if (entityInstance.AlreadyFetched<[MappedFieldNameRelation]>) 
       <[MappedFieldNameRelation]> = RelatedObject<<[RelatedEntityName]>DTO, <[RelatedEntityName]>Entity>(entityInstance.<[MappedFieldNameRelation]>, seenObjects, parents);<[EndIf]><[NextForeach]> 

      return this; 
     } 

     <[ If Not IsSubType ]> 
     /// <summary> 
     /// Get a collection of DTO objects created from entities related to <[CurrentEntityName]>Entity. 
     /// It keeps track of entities previously seen to prevent an infinite loop. 
     /// <summary> 
     protected virtual T[] RelatedArray<T,U>(EntityCollectionBase<U> entities, Hashtable seenObjects, Hashtable parents) where T : class, IDTO<U>, new() where U : EntityBase 
     { 
      if (null == entities) 
      { 
        return null; 
      } 

      T[] arr = new T[entities.Count]; 
      int i = 0; 

      foreach (U entity in entities) 
      { 
       if (parents.Contains(entity)) 
       { 
        return null; 
       } 
      } 

      foreach (U entity in entities) 
      { 
       if (seenObjects.Contains(entity)) 
       { 
        arr[i++] = seenObjects[entity] as T; 
       } 
       else 
       { 
        arr[i++] = new T().FromEntity(entity, seenObjects, parents) as T; 
       } 
      } 
      return arr; 
     } 

     /// <summary> 
     /// Creates a DTO object from the given related <[CurrentEntityName]>Entity entity. 
     /// This is used to populate a single DTO from a single relation of the <[CurrentEntityName]>Entity. 
     /// <summary> 
     protected virtual T RelatedObject<T,U>(U entityInstance, Hashtable seenObjects, Hashtable parents) where T : class, IDTO<U>, new() where U : EntityBase 
     { 
      if (null == entityInstance) 
      { 
       return null; 
      } 

      if (seenObjects.Contains(entityInstance)) 
      { 
       if (parents.Contains(entityInstance)) 
       { 
        return null; 
       } 
       else 
       { 
        return seenObjects[entityInstance] as T; 
       } 
      } 

      return new T().FromEntity(entityInstance, seenObjects, parents) as T; 
     } 

     <[ EndIf]> 
     /// <summary> 
     /// Get a collection of individual DTO objects from the EntityCollectionBase<<[CurrentEntityName]>Entity> collection. 
     /// <summary> 
     public static <[CurrentEntityName]>DTO[] ToDTOArray(EntityCollectionBase<<[CurrentEntityName]>Entity> entities) 
     { 
      Hashtable seenObjects = new Hashtable(); 
      <[CurrentEntityName]>DTO[] arr = new <[CurrentEntityName]>DTO[entities.Count]; 
      for (int i = 0; i < entities.Count; i++) 
      { 
       arr[i] = new <[CurrentEntityName]>DTO().FromEntity(entities[i], seenObjects, new Hashtable()) as <[CurrentEntityName]>DTO; 
      } 
      return arr; 
     } 

     /// <summary> 
     /// Creates a new entity instance and copies over the values of this DTO 
     /// </summary> 
     public <[ If IsSubType ]>override <[SuperTypeName]><[ Else]>virtual <[CurrentEntityName]><[ EndIf]>Entity ToEntity() 
     { 
      return ToEntity(new <[CurrentEntityName]>Entity()); 
     } 

     /// <summary> 
     /// Copies over the values of this DTO into the entity passed in. 
     /// Readonly fields on the entity are NOT copied to the entity from this DTO. 
     /// </summary> 
     public virtual <[CurrentEntityName]>Entity ToEntity(<[CurrentEntityName]>Entity toFill) 
     { 
<[Foreach EntityField CrLf]><[If IsReadOnly ]><[ Else ]>   toFill.<[EntityFieldName]> = this.<[EntityFieldName]>;<[ EndIf ]><[NextForeach]> 

<[ If IsSubType ]>   base.ToEntity(toFill);<[ EndIf]>   
      return toFill; 
     } 

     #region Relation Fields 

<[Foreach RelatedEntity OneToMany CrLf]><[If Not MappedFieldRelationIsHidden]> 
     /// <summary> Gets the EntityCollectionBase with the related entities of type '<[RelatedEntityName]>Entity' which are related to this entity via a relation of type '1:n'. 
     /// If the EntityCollectionBase hasn't been fetched yet, the collection returned will be empty.</summary> 
     public virtual <[RelatedEntityName]>DTO[] <[MappedFieldNameRelation]> { get; set; }<[EndIf]><[NextForeach]> 
<[Foreach RelatedEntity ManyToMany CrLf]><[If Not MappedFieldRelationIsHidden]> 
     /// <summary> Gets the EntityCollectionBase with the related entities of type '<[RelatedEntityName]>Entity' which are related to this entity via a relation of type 'm:n'. 
     /// If the EntityCollectionBase hasn't been fetched yet, the collection returned will be empty.</summary> 
     public virtual <[RelatedEntityName]>DTO[] <[MappedFieldNameRelation]> { get; set; }<[EndIf]><[NextForeach]> 
<[Foreach RelatedEntity ManyToOne CrLf]><[If Not MappedFieldRelationIsHidden]> 
     /// <summary> Gets/sets related entity of type '<[RelatedEntityName]>Entity' which has to be set using a fetch action earlier. If no related entity 
     /// is set for this property, null is returned. This property is not visible in databound grids.</summary> 
     [Browsable(false)] 
     public virtual <[RelatedEntityName]>DTO <[MappedFieldNameRelation]> { get; set; }<[EndIf]><[NextForeach]> 
<[Foreach RelatedEntity OneToOne CrLf]><[If Not MappedFieldRelationIsHidden]> 
     /// <summary> Gets/sets related entity of type '<[RelatedEntityName]>Entity' which has to be set using a fetch action earlier. If no related entity 
     /// is set for this property, null is returned. This property is not visible in databound grids.</summary> 
     [Browsable(false)] 
     public virtual <[RelatedEntityName]>DTO <[MappedFieldNameRelation]> { get; set; }<[EndIf]><[NextForeach]> 

     #endregion 

     #region Custom DTO code 
     <[ UserCodeRegion "CustomDTOCode" ]> 
     // __LLBLGENPRO_USER_CODE_REGION_START CustomDTOCode 
     // __LLBLGENPRO_USER_CODE_REGION_END 
     <[ EndUserCodeRegion ]> 
     #endregion 
    } 
} 

File: dtoExtensions.template

using System; 
using System.Collections.Generic; 
using System.Linq; 
using <[RootNamespace]>; 
using <[RootNamespace]>.EntityClasses; 
using <[RootNamespace]>.CollectionClasses; 
using <[RootNamespace]>.DTOClasses; 
using <[RootNamespace]>.HelperClasses; 

namespace <[RootNamespace]>.DTOClasses 
{ 
    /// <summary> 
    /// Generates extension methods for converting Entities to DTOs 
    /// This class is generated. Do not modify. 
    /// </summary> 
    public static <[If UsePartialClasses]>partial <[EndIf]>class Extensions 
    { 
<[If HasEntity]><[Foreach Entity]> 
     /// <summary>Create a <[CurrentEntityName]> DTO from a <[CurrentEntityName]> entity</summary> 
     /// <returns>The DTO created</returns> 
     public static <[CurrentEntityName]>DTO ToDTO(this <[CurrentEntityName]>Entity entity) 
     { 
      <[CurrentEntityName]>DTO dto = null; 
      if (entity != null) 
       dto = new <[CurrentEntityName]>DTO(entity); 
      return dto; 
     } 

     /// <summary>Create a list of <[CurrentEntityName]>DTO from a <[CurrentEntityName]>Collection</summary> 
     /// <returns>The DTO list created</returns> 
     public static List<<[CurrentEntityName]>DTO> ToDTOs(this <[CurrentEntityName]>Collection collection) 
     { 
      List<<[CurrentEntityName]>DTO> dtoList = new List<<[CurrentEntityName]>DTO>(collection.Count); 
      foreach(<[CurrentEntityName]>Entity entity in collection) 
       dtoList.Add(new <[CurrentEntityName]>DTO(entity)); 
      return dtoList; 
     } 

     /// <summary>Create a list of <[CurrentEntityName]>DTO from a List of <[CurrentEntityName]> entities</summary> 
     /// <returns>The DTO list created</returns> 
     public static List<<[CurrentEntityName]>DTO> ToDTOs(this List<<[CurrentEntityName]>Entity> entities) 
     { 
      return entities.ConvertAll<<[CurrentEntityName]>DTO>(e => new <[CurrentEntityName]>DTO(e)); 
     } 

     /// <summary>From the queryable object, get a list of <[CurrentEntityName]>DTO</summary> 
     /// <returns>The DTO list created</returns> 
     public static List<<[CurrentEntityName]>DTO> ToDTOs(this IQueryable<<[CurrentEntityName]>Entity> queryableEntities) 
     { 
      return queryableEntities.ToList().ConvertAll<<[CurrentEntityName]>DTO>(e => new <[CurrentEntityName]>DTO(e)); 
     } 

     /// <summary>From the queryable object, get a list of <[CurrentEntityName]>DTO</summary> 
     /// <returns>The DTO list created</returns> 
     public static <[CurrentEntityName]>DTO FirstDTO(this IQueryable<<[CurrentEntityName]>Entity> queryableEntities) 
     { 
      <[CurrentEntityName]>DTO dto = null; 
      <[CurrentEntityName]>Entity firstEntity = queryableEntities.First(); 
      if (firstEntity != null) 
       dto = new <[CurrentEntityName]>DTO(firstEntity); 
      return dto; 
     } 
<[NextForeach]><[EndIf]> 
     #region Custom code 
     <[ UserCodeRegion "CustomDTOCode" ]> 
     // __LLBLGENPRO_USER_CODE_REGION_START CustomDTOCode 
     // __LLBLGENPRO_USER_CODE_REGION_END 
     <[ EndUserCodeRegion ]> 
     #endregion 
    } 
} 

File: DTO.tasks

<?xml version="1.0" ?> 
<taskGroup xmlns="http://sd/llblgen/pro/taskGroupElementDefinitions.xsd" name="DTO Templates" isOptional="false" description="General group of tasks which are used DTO templates."> 
    <supportedPlatforms> 
     <platform name=".NET 3.5" /> 
    </supportedPlatforms> 
    <supportedTemplateGroups> 
    <templateGroup name="SelfServicing" /> 
    </supportedTemplateGroups> 
    <taskGroup name="Create Directories"> 
     <task name="DTODirectoryCreator" assemblyFilename="SD.LLBLGen.Pro.TaskPerformers.dll" taskPerformerClass="SD.LLBLGen.Pro.TaskPerformers.DirectoryCreator"> 
      <parameters> 
       <parameter name="folderToCreate" defaultValue="DTOClasses" isOptional="false" description="The folder to create" /> 
       <parameter name="failWhenExistent" defaultValue="false" isOptional="true" description="Flag to signal what to do when the folder already exists. Overrules clearWhenExistent" valueType="boolean" /> 
       <parameter name="clearWhenExistent" defaultValue="false" isOptional="true" description="Flag to signal if an existing folder has to be cleared first. Overruled by failWhenExistent" valueType="boolean" /> 
      </parameters> 
     </task> 
    </taskGroup> 
    <taskGroup name="Create DTO Classes" description="Create DTO Classes"> 
     <task name="DTOInterfaceCreator" assemblyFilename="SD.LLBLGen.Pro.TaskPerformers.dll" taskPerformerClass="SD.LLBLGen.Pro.TaskPerformers.CodeEmitter"> 
      <parameters> 
       <parameter isOptional="false" name="destinationFolder" defaultValue="DTOClasses" /> 
       <parameter isOptional="false" name="failWhenExistent" defaultValue="false" /> 
       <parameter isOptional="false" name="filenameFormat" defaultValue="IDTO.cs" /> 
       <parameter isOptional="false" name="templateID" defaultValue="SD_DTOInterfaceTemplate" /> 
       <parameter isOptional="false" name="emitType" defaultValue="generic" /> 
      </parameters> 
     </task> 
     <task name="DTOClassCreator" assemblyFilename="SD.LLBLGen.Pro.TaskPerformers.dll" taskPerformerClass="SD.LLBLGen.Pro.TaskPerformers.CodeEmitter"> 
      <parameters> 
       <parameter isOptional="false" name="destinationFolder" defaultValue="DTOClasses" /> 
       <parameter isOptional="false" name="failWhenExistent" defaultValue="false" /> 
       <parameter isOptional="false" name="filenameFormat" defaultValue="[elementName]DTO.[extension]" /> 
       <parameter isOptional="false" name="templateID" defaultValue="SD_DTOTemplate" /> 
       <parameter isOptional="false" name="emitType" defaultValue="allEntities" /> 
      </parameters> 
     </task> 
     <task name="DTOExtentionsCreator" assemblyFilename="SD.LLBLGen.Pro.TaskPerformers.dll" taskPerformerClass="SD.LLBLGen.Pro.TaskPerformers.CodeEmitter"> 
      <parameters> 
       <parameter isOptional="false" name="destinationFolder" defaultValue="DTOClasses" /> 
       <parameter isOptional="false" name="failWhenExistent" defaultValue="false" /> 
       <parameter isOptional="false" name="filenameFormat" defaultValue="DTOExtensions.cs" /> 
       <parameter isOptional="false" name="templateID" defaultValue="SD_DTOExtentionsTemplate" /> 
       <parameter isOptional="false" name="emitType" defaultValue="generic" /> 
      </parameters> 
     </task> 
    </taskGroup> 
</taskGroup> 

Infine, aggiungere il seguente al posto appropriato nel file * .preset. Questo definirà l'attività di generazione del codice sopra la tua preimpostazione di generazione.

<taskGroupPreset name="DTO Templates"> 
    <taskGroupPreset name="Create Directories"> 
    <taskPreset name="DTODirectoryCreator" /> 
    </taskGroupPreset> 
    <taskGroupPreset name="Create DTO Classes"> 
    <taskPreset name="DTOInterfaceCreator" /> 
    <taskPreset name="DTOEntityInterfaceCreator" /> 
    <taskPreset name="DTOBaseClassCreator" /> 
    <taskPreset name="DTOClassCreator" /> 
    <taskPreset name="DTOExtentionsCreator" /> 
    </taskGroupPreset> 
</taskGroupPreset> 
Problemi correlati