2011-10-27 35 views
6

Như tôi đã hiểu, LLBLGen Pro không thể tạo POCO trên các thực thể riêng của nó (xem tại đây: http://www.llblgen.com/Pages/featuresLLBLGenPro.aspx).T4 Để tạo POCO trên các thực thể LLBLGen Pro?

Có ai đã viết một T4 sẽ tạo ra các lớp POCO tương ứng với các thực thể LLBLGen Pro và tạo logic chuyển đổi thích hợp để đi đến và từ một thực thể và POCO không? Có ai khác đưa ra một giải pháp không liên quan đến việc viết bằng tay tấn mã chuyển đổi không?

+0

Mặc dù tôi chưa tạo chính xác những gì bạn không tạo mẫu T4 sẽ không thực sự khó khăn nếu bạn sử dụng studio mẫu có thể tải xuống từ trang web llblgen. Tôi tạo ra một mẫu mà sẽ tạo ra sp để làm sao chép thủ công (không hỏi!) Và những gì bạn cần làm là đơn giản hơn nhiều. Đối với ánh xạ, bạn chỉ có thể sử dụng AutoMapper. Bạn đang cố gắng đạt được gì khi có POCO? –

+0

Cảm ơn thượng cổ. Những gì chúng tôi muốn đạt được bằng cách sử dụng POCO là ngoài phạm vi cho câu hỏi nhưng là một câu hỏi hay về chính nó. Lý do sang một bên, tôi chắc chắn tin rằng nó có thể làm điều này nhưng tôi đã hy vọng một người nào đó đã có một T4 đã được tạo ra và công khai có sẵn. – jakejgordon

Trả lời

6

Chúng tôi đã tạo DTO từ LLBLGen thay vì sử dụng T4.

Chúng tôi cần tạo DTO từ Pháp nhân. Đây không phải là về mặt kỹ thuật POCO vì chúng có phương pháp ToEntity()FromEntity(), nhưng có lẽ điều này sẽ phù hợp với bạn.

Chúng tôi đã tạo một giao diện IDTO<T> sau đó được triển khai bởi các lớp DTO (một cho mỗi thực thể). Thay vì sửa đổi mẫu thực thể, chúng tôi đã thêm DTOExtension các phương thức sẽ chuyển đổi Pháp nhân thành DTO (cũng như nhiều chuyển đổi trợ giúp khác).

Dưới đây là các tệp mẫu bạn có thể sử dụng trong LLBLGen v2.6. Trình thiết kế mẫu trong phiên bản 3 dễ sử dụng hơn nhiều và bạn có thể chuyển đổi nhiều mã này cho phiên bản 3 nếu bạn cần.

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> 

Cuối cùng, thêm dòng sau vào nơi thích hợp trong tập tin * .preset của bạn. Điều này sẽ xác định tác vụ tạo mã ở trên trong cài đặt trước thế hệ của bạn.

<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> 
Các vấn đề liên quan