Skip to content

Repository files navigation

Nuget Downloads Paypal Donate Pull Request Check

Autofac.EasyPropInject (by Malte)

Attribute based property injection for Autofac, without any other helper libraries.
Decorate a property with [FromAutofac] and it is resolved from the container while the component is activated — public, protected and private properties all work.
Property metadata is collected once per type and written through emitted setters, so after the first resolve the injection costs close to nothing.

Requirements

Autofac.EasyPropInject requires Autofac 9.x and a project targeting net10.0 or anything compatible with netstandard2.1.

External Libraries
This library uses the following library to achieve its functionality:

Install

Using the NuGet package manager:

Install-Package Autofac.EasyPropInject

Using the .NET CLI:

dotnet add package Autofac.EasyPropInject

Enable it in your application:

// Startup.cs / Program.cs
using Autofac;
using Autofac.EasyPropInject;

var builder = new ContainerBuilder();

builder.AddEasyPropInject();

// Add your services as usual
builder.RegisterType<MyService>().As<IMyService>();

IContainer container = builder.Build();

Note: the call can go anywhere while configuring the builder — before, after or in between your registrations. Older versions of this README claimed it had to come first; that is no longer the case and it is covered by tests.

Set up the Autofac container the way your framework expects — see the Autofac integration documentation.

Configuration

No configuration is required to use Autofac.EasyPropInject. If you want to change the defaults, pass a callback to AddEasyPropInject:

builder.AddEasyPropInject(options =>
{
    // Restore the behaviour of 2.x: overwrite a property with null when it cannot be resolved
    options.UnresolvedBehavior = UnresolvedPropertyBehavior.SetNull;
});

Configuration Entries and Their Meanings

Option Description Default Value Type
UnresolvedBehavior What happens to a decorated property whose service is not registered in the container. Skip leaves the property untouched, so a value assigned in the constructor survives. SetNull overwrites it with null, which is what EasyPropInject 2.x and earlier did Skip UnresolvedPropertyBehavior

Usage

The Attribute

To inject a property, decorate it with FromAutofacAttribute.
This is the simple way — no constructor plumbing, no service locator.

Arguments:

Name Description
Type resolveFromRegisteredType Look this type up in the container instead of the declared property type. If null, empty, or not given, the declared property type is used.

Examples

using Autofac.EasyPropInject.Annotations;

public class MyClass : IMyInterface
{
    public MyClass(ISomeOtherInterface someService)
    {
    }

    [FromAutofac]
    public IUnitOfWork Unit { get; set; }

    [FromAutofac] // Since 1.2.5: support for protected properties
    protected IMyService ServiceProtected { get; set; }

    [FromAutofac] // Since 1.2.5: support for private properties
    private IMyService2 ServicePrivate { get; set; }

    [FromAutofac(typeof(IUnitOfWork))]
    public UnitOfWorkBaseClass Unit2 { get; set; }
}

Once IMyInterface is resolved and activated, EasyPropInject resolves every decorated property from the current container. Since 3.0.0, private and protected properties declared on a base class are picked up as well.

The property must have a setter — init accessors are fine. A decorated property without one throws an InvalidOperationException naming the type and the property.

Resolving as a Different Type

[FromAutofac(typeof(IUnitOfWork))] resolves IUnitOfWork from the container and assigns it to a property declared as UnitOfWorkBaseClass.

Warning: this feature is handy but truly unsafe. No compile time check and no type check at resolve time can tell you that the registered implementation of IUnitOfWork really is a UnitOfWorkBaseClass — be sure of what you are doing.

Unresolvable Properties

By default a property whose service is not registered is left exactly as it is:

public class MyClass : IMyInterface
{
    public MyClass()
    {
        this.Optional = new NullLogger();
    }

    [FromAutofac]
    public ILogger Optional { get; set; }   // stays a NullLogger if ILogger is not registered
}

Set UnresolvedBehavior to UnresolvedPropertyBehavior.SetNull to get the 2.x behaviour back, where the property is overwritten with null instead.

Performance

EasyPropInject sits in the resolve pipeline of every component, so it is built to get out of the way. Version 3.0.0 resolves roughly three times faster than 2.x — measured over 2,000,000 resolves on .NET 10:

Scenario 2.x 3.0.0
Component with [FromAutofac] properties ~3.2 s ~1.0 s
Component without any attributes ~2.0 s ~0.7 s

What changed:

  • Metadata is cached per type. The decorated properties, the Autofac Service to resolve for each of them and the setter to use are worked out once and reused. Up to 2.x every resolve called GetProperties() on the concrete type and asked every single property for its attributes.
  • Types without decorated properties cost a dictionary lookup. They cache an empty result and leave the middleware immediately — which is why components that never use the attribute got faster too.
  • Setters are emitted, not reflected. Each property gets a DynamicMethod that assigns the value directly, which avoids the overhead and the boxing of PropertyInfo.SetValue. Where dynamic code is not available (AOT), it falls back to reflection automatically.
  • Shared instances are injected once, when they are activated, and skipped explicitly on every resolve after that.
  • One middleware instance per container instead of one per component registration.

Changelog

See CHANGELOG.md.

Contribute / Donations

If you have any ideas to improve my projects, feel free to send a pull request.

If you like my work and want to support me (or want to buy me a coffee/beer), PayPal donations are more than appreciated.

Paypal Donate Nuget

About

An extension i created to make it possible to to inject properties by attribute, without any other helper libs.

Topics

Resources

Stars

Watchers

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages