Giter VIP home page Giter VIP logo

eflazyloading.fody's Introduction

SpatialFocus.EFLazyLoading.Fody

An EF Lazy Loading Fody plugin.

Nuget Build & Publish FOSSA Status

A Fody plugin to inject EF lazy-loader and load statements for readonly collections.

If you are going for a clean DDD implementation, you might want to encapsulate access to navigation collection properties and expose those as readonly collections only. If you now reference your backing field within your entity, there is no chance for lazy loading to kick in. For this to work you would have to pollute your entity with EF infrastructure knowledge, as described in this issue. This Fody plugin deals exactly with this problem and does the heavy lifting described in the issue mentioned.

Usage

See also Fody usage.

NuGet installation

Install the SpatialFocus.EFLazyLoading.Fody NuGet package and update the Fody NuGet package:

PM> Install-Package Fody
PM> Install-Package SpatialFocus.EFLazyLoading.Fody

The Install-Package Fody is required since NuGet always defaults to the oldest, and most buggy, version of any dependency.

Add to FodyWeavers.xml

Add <SpatialFocus.EFLazyLoading/> to FodyWeavers.xml

<Weavers>
    <SpatialFocus.EFLazyLoading/>
</Weavers>

Overview

This fody plugin performs the following actions:

  • Adds a field private readonly Action<object, string>? lazyLoader to your entity
  • Overloads existing constructors with an additional Action<object, string>? lazyLoader parameter
  • For every ReadOnlyCollection or IReadOnlyCollection it finds the corresponding backing field (propertyname, _propertyname, m_propertyname)
  • For every access (including methods & properties) to this backing field (except the navigation property itself), it adds the corresponding this.lazyLoader?.Invoke statement

Before code:

public class Customer
{
    private readonly List<Order> orders = new();

    public Customer(string name)
    {
        Name = name;
    }

    public int NumberOfOrders => this.orders.Count;

    public virtual IReadOnlyCollection<Order> Orders => this.orders.AsReadOnly();

    public int Id { get; protected set; }

    public string Name { get; protected set; }

    public void AddOrder(Order order) => this.orders.Add(order);

    public void ClearOrders() => this.orders.Clear();

    public void RemoveOrder(Order order) => this.orders.Remove(order);
}

What gets compiled

public class CustomerWeaved
{
    private readonly Action<object, string>? lazyLoader;
    private readonly List<Order> orders = new();

    public CustomerWeaved(string name)
    {
        Name = name;
    }

    // For every constructor a constructor overload with Action<object, string> lazyLoader will be added,
    // and the original constructor will be called
    // See https://docs.microsoft.com/en-us/ef/core/querying/related-data/lazy#lazy-loading-without-proxies
    protected CustomerWeaved(string name, Action<object, string> lazyLoader) : this(name)
    {
        this.lazyLoader = lazyLoader;
    }

    public int NumberOfOrders
    {
        get
        {
            this.lazyLoader?.Invoke(this, "Orders");
            return this.orders.Count;
        }
    }

    // Access via navigation property will trigger default lazy loading behaviour
    public virtual IReadOnlyCollection<Order> Orders => this.orders.AsReadOnly();

    public int Id { get; protected set; }

    public string Name { get; protected set; }

    public void AddOrder(Order order)
    {
        this.lazyLoader?.Invoke(this, "Orders");
        this.orders.Add(order);
    }

    public void ClearOrders()
    {
        this.lazyLoader?.Invoke(this, "Orders");
        this.orders.Clear();
    }

    public void RemoveOrder(Order order)
    {
        this.lazyLoader?.Invoke(this, "Orders");
        this.orders.Remove(order);
    }
}

Important remarks

Classes with an already exsting lazyloader field or any constructor with a lazyloader named parameter will be skipped. Only classes with ReadOnlyCollection<T> or IReadOnlyCollection<T> navigation properties will be weaved. The generic type of these collections must be class (excluding strings, enums and value types) to be considered for weaving.

Include or exclude namespaces

These config options are configured by modifying the SpatialFocus.EFLazyLoading node in FodyWeavers.xml

ExcludeNamespaces

A list of namespaces to exclude.

Can take two forms.

As an element with items delimited by a newline.

<SpatialFocus.EFLazyLoading>
    <ExcludeNamespaces>
        Foo
        Bar
    </ExcludeNamespaces>
</SpatialFocus.EFLazyLoading>

Or as a attribute with items delimited by a pipe |.

<SpatialFocus.EFLazyLoading ExcludeNamespaces='Foo|Bar'/>

IncludeNamespaces

A list of namespaces to include.

Can take two forms.

As an element with items delimited by a newline.

<SpatialFocus.EFLazyLoading>
    <IncludeNamespaces>
        Foo
        Bar
    </IncludeNamespaces>
</SpatialFocus.EFLazyLoading>

Or as a attribute with items delimited by a pipe |.

<SpatialFocus.EFLazyLoading IncludeNamespaces='Foo|Bar'/>

Wildcard support

Use * at the beginning or at the end of an in- or exclude for wildcard matching.

To include the namespace and all sub-namespaces, simply define it like this:

<SpatialFocus.EFLazyLoading>
    <IncludeNamespaces>
        Foo
        Foo.*
    </IncludeNamespaces>
</SpatialFocus.EFLazyLoading>

Combination of exclude and include

You can combine excludes and includes, excludes overrule the includes if both match.

License

FOSSA Status


Made with ❤️ by Spatial Focus

eflazyloading.fody's People

Contributors

dresel avatar pergerch avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.