1

I want to add a Lazy to my class. To access non-static members inside the initialization method of the Lazy, the best-practice method (see https://stackoverflow.com/a/14029443/10406502) is to define the Lazy inside the default constructor. This is not possible in my project, because it's a partial class and the default constructor is already defined by some auto-generated code (Entity Framework).

Is there a way to use Lazy accessing non-static class members without implementing it in the default constructor?

André Reichelt
  • 1,484
  • 18
  • 52

1 Answers1

1

Thanks to Robert Harvey, I found the following solution: First, you have to add some stuff to your data model template MyModeName.tt, which you can find under the MyModelName.edmx in your project. I added a new partial method private partial void OnConstructorCompletion(); and called it at the end of the constructor. I modified the document as follows (lines 27-67):

<#=codeStringGenerator.EntityClassOpening(entity)#>
{
    private partial void OnConstructorCompletion();

<#
    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
    var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
    var complexProperties = typeMapper.GetComplexProperties(entity);

    if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
    {
#>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public <#=code.Escape(entity)#>()
    {
<#
        foreach (var edmProperty in propertiesWithDefaultValues)
        {
#>
        this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
<#
        }

        foreach (var navigationProperty in collectionNavigationProperties)
        {
#>
        this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#
        }

        foreach (var complexProperty in complexProperties)
        {
#>
        this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
        }
#>

        OnConstructorCompletion();
    }

Next, I implemented the method where required inside of my entity class:

public partial class MyEntity
{
    public Lazy<ICollection<MyNavigationEntity>> NavigationProperty;

    private partial void OnConstructorCompletion()
    {
        NavigationProperty= new Lazy<ICollection<MyNavigationEntity>>(() =>
        {
            DatabaseEntities db = (DatabaseEntities)EntityContextExtensions.GetDbContextFromEntity(this);

            return db.MyNavigationEntity
                .Where(ne => ne.ID == this.ID_MyNavigationEntity)
                .ToHashSet();
        });
    }
}
André Reichelt
  • 1,484
  • 18
  • 52