Implement an Interface in my POCO's

Discussion of open issues, suggestions and bugs regarding Entity Developer - ORM modeling and code generation tool
Post Reply
csl
Posts: 4
Joined: Thu 23 Jan 2014 19:38

Implement an Interface in my POCO's

Post by csl » Thu 18 Jun 2015 13:19

I would like the NHibernateEntities template to implement a custom Interface to each of the entities (just a simple interface with common fields like Id, CreatedAt, ModifiedAt etc)

How would I go about doing this or is it a case of hard-coding this into the template?

MariiaI
Devart Team
Posts: 1472
Joined: Mon 13 Feb 2012 08:17

Re: Implement an Interface in my POCO's

Post by MariiaI » Fri 19 Jun 2015 08:25

You can try adding a new custom template in your model with the following code:

Code: Select all

<#
// NHibernate template for Devart Entity Developer C# code generation.
// Copyright (c) 2008-2015 Devart. All rights reserved.
#>
<#@ template language="C#" #>
<#@ include file="Validation.tmpl" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ property name="HeaderTimestampVersionControlTag" category="Generation" type="System.String" description="If this option is set, the standard date/time-stamp in the file header will be replaced with the specified tag (e.g. a version control tag for Subversion, Git, etc.)" #>
<#@ property name="InterfacesOutput" category="Output" type="OutputInfo" editor="OutputInfoEditor" description="Specifies output for the generated entity classes." #>
<#@ property name="FilePerClass" category="Output" default="True" type="System.Boolean" description="If it is set to True, each model class will be placed to the separate file when generating code, otherwise, all model classes will be placed into a single file." #>
<#@ property name="ModelNameAsFilesPrefix" category="Output" type="System.Boolean" default="True" description="If it is set to True, then the main model file name will be used as a prefix for the names of the files generated for entities. The property can be used, if File Per Class is turned on." #>
<#@ property name="NHibernateV3Compatible" displayName="NHibernate V3 Compatible" category="Generation" default="False" type="System.Boolean" description="Determines the types used for collection properties of the Set type. If it is set to True, the Iesi.Collections.dll types are used for collection properties of the Set type. This requires NHibernate version 3. Otherwise, the .NET Framework System.dll types are used for collection properties of the Set type - this requires Nhibernate of version 4 and higher." #>
<#

  // Settings
  string baseFileName = model.FileName;
  output.Extension = ".cs";

  // Begin generation
  if (!FilePerClass) {
    output.PushOutputRedirection(InterfacesOutput, baseFileName + ".Interfaces.Designer");
    GenerateFileHeader();
  }

  string defaultNamespace = codeProvider.GetValidIdentifier(model.GetDefaultNamespace());

  //------------------------------------------------------------------------------
  // Class generation for entities
  //------------------------------------------------------------------------------
  var namespaces = from cls in model.Classes.Cast<HibernateClass>()
    let namespaceName = !String.IsNullOrEmpty(cls.Namespace) ? codeProvider.GetValidIdentifier(cls.Namespace) : defaultNamespace
    group cls by namespaceName;

  foreach (var _namespace in namespaces) {
    if (!FilePerClass) {
#>

namespace <#= _namespace.Key #>
{
<#
    }
    foreach (HibernateClass cls in _namespace) {
      if (FilePerClass) {
        string rootFileName = ModelNameAsFilesPrefix ? baseFileName + ".I" + cls.Name : ".I" + cls.Name;
        output.Extension = ".cs";
        output.PushOutputRedirection(InterfacesOutput, rootFileName);
        GenerateFileHeader();
#>

namespace <#= _namespace.Key #>
{
<#
      }
#>
 <#= codeProvider.FormatClassAccess(cls.Access) #> interface <#= codeProvider.GetValidIdentifier("I" + cls.Name) #>
 {
<#
      // Class properties
      foreach (HibernateProperty property in cls.Properties) {
	      if (!(bool)property.GetProperty("Unimplemented")) {
          string propType = GetPropertyTypeName(property, _namespace.Key, defaultNamespace);
          string propName = codeProvider.GetValidIdentifier(property.Name);
#>
            <#= propType #> <#= codeProvider.GetValidIdentifier(propName) #>
            {
                get;
                set;
            }

<#
		    }
      }

      // Class navigation properties  
      foreach (HibernateRelationProperty relationProperty in cls.RelationProperties) {
        if (relationProperty.Generate) {
          if(!(bool)relationProperty.GetProperty("Unimplemented")) {
              string propName = codeProvider.GetValidIdentifier(relationProperty.Name);
              string propType = GetRelationPropertyTypeName(relationProperty, _namespace.Key, defaultNamespace);
#>
            <#= propType #> <#= propName #>
            {
                get;
                set;
            }

<#
          }
        }
      }
#>
    }
<#
      if (FilePerClass) {
#>

}
<#
        output.PopOutputRedirection();
      }
    
    } // End of generation

    if (!FilePerClass) {
#>

}
<#
    }
  } // End of namespace generation
  output.PopOutputRedirection();
  // End of generation
#>
<#+
  //////////////////////////////////////////////////////////////////////////////////
  //
  // Method GenerateFileHeader()
  // Comments and namespaces for each generated file.
  //
  //////////////////////////////////////////////////////////////////////////////////
  private void GenerateFileHeader() {
#>
//------------------------------------------------------------------------------
// This is auto-generated code.
//------------------------------------------------------------------------------
// This code was generated by Entity Developer tool using NHibernate template.
// <#= String.IsNullOrEmpty(HeaderTimestampVersionControlTag) ? "Code is generated on: " + DateTime.Now : HeaderTimestampVersionControlTag #>
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Collections.Generic;
<#+
  }
#>
<#+ 
  //////////////////////////////////////////////////////////////////////////////////
  //
  // Method GetRelationPropertyTypeName(HebirnateRelationProperty relationProperty, string parentNamespace, string defaultNamespace)
  // Returns the interface or type name of navigation property.
  //
  //////////////////////////////////////////////////////////////////////////////////
  private string GetRelationPropertyTypeName(HibernateRelationProperty relationProperty, string parentNamespace, string defaultNamespace) {

    BaseClass relationClass = relationProperty.RelationClass;
    if ((relationProperty.Multiplicity == Multiplicity.Many && relationProperty.OppositeRelationProperty.Multiplicity == Multiplicity.Many) &&
       ((HibernateAssociation)relationProperty.Association).ManyToManyComponent != null)
      relationClass = ((HibernateAssociation)relationProperty.Association).ManyToManyComponent;

    string relationClassName = codeProvider.GetValidIdentifier(relationClass.Name);
    string nspace = !string.IsNullOrEmpty(((IHibernateClass)relationClass).Namespace) ? codeProvider.GetValidIdentifier(((IHibernateClass)relationClass).Namespace) : defaultNamespace;
    if (nspace != parentNamespace)
      relationClassName = nspace + "." + relationClassName;

    if (relationProperty.Multiplicity != Multiplicity.Many)
      return relationClassName;

    if (relationProperty.IsPropertyExist("CollectionTypeName") && !string.IsNullOrEmpty(relationProperty.GetProperty("CollectionTypeName") as string))
	  return codeProvider.GetNullableType(false, relationProperty.GetProperty("CollectionTypeName"));

    switch (relationProperty.CollectionType) { 
      case HibernateCollectionType.Set:
        if (relationProperty.Generic) {
		      if (NHibernateV3Compatible)
            return string.Format("Iesi.Collections.Generic.ISet<{0}>", relationClassName);
          else
            return string.Format("ISet<{0}>", relationClassName);
        }
        else
          return "Iesi.Collections.ISet";
      case HibernateCollectionType.List:
      case HibernateCollectionType.Bag:
      case HibernateCollectionType.Idbag:
        if (relationProperty.Generic)
          return string.Format("IList<{0}>", relationClassName);
        else
          return "IList";
      case HibernateCollectionType.Map:
        if (relationProperty.Generic) {
          string indexType;
          if (relationProperty.IndexType is BaseClass) { 
            indexType = codeProvider.GetValidIdentifier(((BaseClass)relationProperty.IndexType).Name);
            string classTypeNamespace = !string.IsNullOrEmpty(((IHibernateClass)relationProperty.IndexType).Namespace) ? codeProvider.GetValidIdentifier(((IHibernateClass)relationProperty.IndexType).Namespace) : defaultNamespace;
            if (classTypeNamespace != parentNamespace)
              indexType = classTypeNamespace + "." + indexType;
          }
          else 
            indexType = codeProvider.GetNullableType(false, relationProperty.IndexType);
          return string.Format("IDictionary<{0},{1}>", indexType, relationClassName);
        }
        else
          return "IDictionary";
      case HibernateCollectionType.Array:
        return relationClassName + "[]";
      default:
        throw new NotSupportedException(string.Format("CollectionType is not supported on {0}.", relationProperty.Name));
    }
   }
#>
<#+ 
  //////////////////////////////////////////////////////////////////////////////////
  //
  // Method GetRelationTypeName(HebirnateProperty property, string parentNamespace, string defaultNamespace)
  // Returns the type name of property.
  //
  //////////////////////////////////////////////////////////////////////////////////
  private string GetPropertyTypeName(HibernateProperty property, string parentNamespace, string defaultNamespace) {

        string propertyDataType = string.Empty;
        if (property.IsComplexType || property.IsEnumType) {
          string nspace = !string.IsNullOrEmpty(((IHibernateClass)property.Type).Namespace) ? codeProvider.GetValidIdentifier(((IHibernateClass)property.Type).Namespace) : defaultNamespace;
          propertyDataType = codeProvider.GetValidIdentifier(property.Type.ToString());
          if (nspace != parentNamespace)
            propertyDataType = nspace + "." + propertyDataType;
          if (property.IsEnumType && property.Nullable)
            propertyDataType = codeProvider.FormatNullable(propertyDataType);
          }
        else
          propertyDataType = codeProvider.GetNullableType(property.Nullable, property.Type);

     return propertyDataType;
   }
#>
JIC: this code is basic, you can modify it so that it suits your scenario more completely.

To add a new custom template in your model navigate to Tools > Entity Developer > Model Explorer, right-click on the Templates node > New Blank Template.
Another way: add any predefined template (right-click on Templates > Add Template), then right-click on a newly added template > Copy to Model Folder. After this, open it (by double-click) and modify it with embedded T4 Editor.

Please tell us if this helps.

Post Reply