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?

9
  • 1
    private Lazy<int> lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y)); Commented Oct 5, 2021 at 14:34
  • @RobertHarvey Doesn't work, because you can't access non-static members inside Func<int> (in your example). Commented Oct 5, 2021 at 14:38
  • What non-static members? Commented Oct 5, 2021 at 14:39
  • @RobertHarvey See the question linked in the OP. That does e.g. new Lazy<int>(() => X + Y) where X and Y are instance members. Commented Oct 5, 2021 at 14:39
  • 1
    You'll have to do a bit of poking around on the Internet, but I'm pretty sure this is the right approach. See also entityframework.net/knowledge-base/31793997 Commented Oct 5, 2021 at 14:50

1 Answer 1

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();
        });
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.