DryIoC won't inject properties into ASP.NET Core MVC controller

2.2k Views Asked by At

I'm using https://bitbucket.org/dadhi/dryioc/src/589e7c0b356a/NetCore/src/DryIoc.AspNetCore.Sample as baseline. Tried to implement an attribute-based property injection selector with the following:

private static PropertyOrFieldServiceInfo GetImportedPropertiesAndFields(MemberInfo m, Request req)
    {
        var import = (DependencyAttribute)m.GetAttributes(typeof(DependencyAttribute)).FirstOrDefault();

        return import == null ? null : PropertyOrFieldServiceInfo.Of(m)
            .WithDetails(ServiceDetails.Of(import.ContractType, import.ContractName), req);
    }

where DependencyAttribute marks the properties to be injected. Without embedding this solution into a ASP.NET MVC Core application, it works fine. When I try to make it inject properties in controllers with [Dependency] attribute within an ASP.NET Core application using .WithDependencyInjectionAdapter(...), it won't work, it injects (and intercepts) only those classes, what were registered after taking over the services in ConfigureServices (and in .AddDryIoc<TCompositionRoot> afterwards).

Code parts what I use:

public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        return services.AddDryIoc<CompositionRoot>();
    }

DI class:

public static class DI
{
    public static readonly PropertiesAndFieldsSelector SelectPropertiesAndFieldsWithDependencyAttribute = PropertiesAndFields.All(withInfo: GetImportedPropertiesAndFields);

    public static IServiceProvider AddDryIoc<TCompositionRoot>(this IServiceCollection services)
    {
        var logger = InfrastructureFactory.CreateDefaultNLogger().CreateLogger<Startup>();

        var container = new Container()
            .WithDependencyInjectionAdapter(services, throwIfUnresolved: type => type.Name.EndsWith("Controller"))
            .With(rules => rules.With(SelectPropertiesAndFieldsWithDependencyAttribute).WithoutThrowOnRegisteringDisposableTransient());

        container.RegisterMany<TCompositionRoot>();
        container.Resolve<TCompositionRoot>();

        logger.LogInformation("Verifying DryIoC resolutions...");

        var resolutionErrors = container.VerifyResolutions();

        if (resolutionErrors != null && resolutionErrors.Any())
        {
            foreach (var errors in container.VerifyResolutions())
            {
                logger.LogError($"DryIoC resolution error for type {errors.Key.ServiceType} : {errors.Value.Message} ({errors.Value.StackTrace})");
            }

            logger.LogWarning("DryIoC resolutions are WRONG.");
        }
        else
        {
            logger.LogInformation("DryIoC resolutions are OK.");
        }

        return container.Resolve<IServiceProvider>();
    }

    #region DryIoc Property Dependency Resolver helper
    private static PropertyOrFieldServiceInfo GetImportedPropertiesAndFields(MemberInfo m, Request req)
    {
        var import = (DependencyAttribute)m.GetAttributes(typeof(DependencyAttribute)).FirstOrDefault();

        return import == null ? null : PropertyOrFieldServiceInfo.Of(m)
            .WithDetails(ServiceDetails.Of(import.ContractType, import.ContractName), req);
    }
    #endregion

}

Additional information:

  1. Constructor injection is working in controllers.
  2. Searched DryIOC Container configuration for property injection thoroughly, but it is about a WebApi application, not the case I try.
  3. I tried to switch the order of .WithDependencyInjectionAdapter(...) and .With(rules => ...) with no luck.
  4. Interception not working for controllers also. I'm using @dadhi's recommendation for interception: https://bitbucket.org/dadhi/dryioc/wiki/Interception . BTW, how do you register an interceptor for a Controller with Castle and DryIoC?
  5. I won't copy CompositionRoot class here; it is boring, long and not relevant.

Any ideas to get controller property injection and controller method interception work?

1

There are 1 best solutions below

3
On BEST ANSWER

Please specify AddControllersAsServices() on configured service collection. This explains why.

The Sample is already including this, as well as property injection example.