dadhi / DryIoc

DryIoc is fast, small, full-featured IoC Container for .NET
MIT License
988 stars 122 forks source link

Is there anyway to apply ConcreteTypeDynamicRegistrations to Rules.MicrosoftDependencyInjectionRules? #555

Closed caoyanmin closed 1 year ago

caoyanmin commented 1 year ago

I create the rules follow the code: var rules = Rules.Default.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient).WithMicrosoftDependencyInjectionRules(); or var rules = Rules.MicrosoftDependencyInjectionRules.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient); but it doesn't work.

dadhi commented 1 year ago

@caoyanmin I wrote this simple example, and it works for me in DryIoc v5.3.2:

using System;
using DryIoc;

public class Program
{
    public static void Main()
    {
        var c = new Container(Rules.MicrosoftDependencyInjectionRules.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient));
        var o = c.Resolve<OtherService>();

        Console.WriteLine(o.Dependency);
    }

    internal class Dependency
    {
    }

    internal class OtherService
    {
        public readonly Dependency Dependency;
        public OtherService(Dependency dependency) => Dependency = dependency;
    }
}
caoyanmin commented 1 year ago

@dadhi Thank you for your answer! But when I build a IHost with the Container, I got a exception. The code is:

using DryIoc;
using DryIoc.Microsoft.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace DryIocDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var rules = Rules.MicrosoftDependencyInjectionRules.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient);

            var container = new Container(rules);

            var host = Host.CreateDefaultBuilder()
                .UseServiceProviderFactory(new DryIocServiceProviderFactory(container))
                .ConfigureServices(services =>
                {
                    services.AddSingleton<IService, Service>();
                }).Build();

            // When I resolve IService, I got a exception.
            var resolveFromInterface = container.Resolve<IService>();
            resolveFromInterface.SayHello();

            var resolveFromImplement = container.Resolve<Service>();
            resolveFromImplement.SayHello();

            host.RunAsync();
        }
    }

    public interface IService
    {
        void SayHello();
    }

    public class Service : IService
    {
        public void SayHello()
        {
            Console.WriteLine("Hello DryIoc");
        }
    }
}
dadhi commented 1 year ago

Hmm, ok. Will check Tomorrow.

dadhi commented 1 year ago

@caoyanmin Looking at it again, I am not sure that the problem is about the usage of WithConcreteTypeDynamicRegistrations. Based on the fact that the IService is not resolved, seems like your registration not went into the container. Could you check that by changing the order of extension calls on the builder?

var host = Host.CreateDefaultBuilder()
    .ConfigureServices(services =>
    {
        services.AddSingleton<IService, Service>();
    })
    .UseServiceProviderFactory(new DryIocServiceProviderFactory(container))
    .Build();
caoyanmin commented 1 year ago

@caoyanmin Looking at it again, I am not sure that the problem is about the usage of WithConcreteTypeDynamicRegistrations. Based on the fact that the IService is not resolved, seems like your registration not went into the container. Could you check that by changing the order of extension calls on the builder?

var host = Host.CreateDefaultBuilder()
    .ConfigureServices(services =>
    {
        services.AddSingleton<IService, Service>();
    })
    .UseServiceProviderFactory(new DryIocServiceProviderFactory(container))
    .Build();

It doesn't work.

dadhi commented 1 year ago

@caoyanmin What .NET version are you targeting and what DryIoc version is in use? Plus, could you provide the whole example app for me to check?

caoyanmin commented 1 year ago
@dadhi Here is the full demo project. This table show the result when I use different rules: Rules Resolve Interface From Container Resolve Implement From Container Resolve Interface From ServiceProvider Resolve Implement From ServiceProvider
Rules.MicrosoftDependencyInjectionRules
Rules.MicrosoftDependencyInjectionRules.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient)
Rules.Default.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient)
Rules.Default.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient).WithMicrosoftDependencyInjectionRules()
dadhi commented 1 year ago

@caoyanmin Hi, thanks for the well-prepared example. Indeed, there is the bug going on here. I have provided the workaround in the PR for now: https://github.com/caoyanmin/DryIocDemo/pull/1

dadhi commented 1 year ago

@caoyanmin Hi, the fix is pushed to the Nuget with DryIoc.Microsoft.DependencyInjection v6.1.1. The thing is, you still need to pass RegistrySharing.Share as the second argument to new DryIocServiceProviderFactory(container,RegistrySharing.Share))`.

caoyanmin commented 1 year ago

@dadhi Thank you for your help! I update the package to the last version, it works correctly.