.NET 6 Dependency Injection override

Viewed 401

I want to inject a specific instance (not wired up by DI) as a parameter to my constructor using Microsoft DI and .NET 6. In the example below I'd like to have an instance of MyClass (called myClassSpecial) with the constructor parameters instances of MyInterface1Impl1 and MySpecialImpementation.

EDIT 1
In Unity there is DependencyOverride so basically I guess that this is what I'm looking for in .NET 6 DI ?

EDIT 2
NB: The class Test below does not have access to the concrete implementations MyClass, MyInterface1Impl1, MyInterface1Impl2, but just the interfaces. The classes are loaded dynamically (I just added the AddSingleton lines in case that anyone wants to run the example)

I appreciate any help !

King regards Magnus

// Testprogam
var test = new Test();
test.Show();


// Expected output

MyInterface1Impl1
MyInterface1Impl2
MyInterface1Impl1
MY SPECIAL STUFF
public class MyClass : IMyClass
{
    private readonly IMyInterface1 myInterface1;
    private readonly IMyInterface2 myInterface2;
    public MyClass(IMyInterface1 myInterface1, IMyInterface2 myInterface2)
    {
        this.myInterface1 = myInterface1;
        this.myInterface2 = myInterface2;
    }

    public void ShowInfo()
    {
        Console.WriteLine(myInterface1.GetInformation);
        Console.WriteLine(myInterface2.GetInformation);
    }
}

public class Test
{
    private IMyClass myClass;
    private IMyClass myClassSpecial;

    public Test()
    {
        var host = Host.CreateDefaultBuilder().
            ConfigureServices((context, services) =>
        {
            services.AddSingleton<IMyClass, MyClass>();
            services.AddSingleton<IMyInterface1, MyInterface1Impl1>();
            services.AddSingleton<IMyInterface2, MyInterface1Impl2>();
        }).Build();                      
        
        myClass = ActivatorUtilities.GetServiceOrCreateInstance<IMyClass>(host.Services);


        var mySpecialImpementation = new MySpecialImpementation();
        myClassSpecial = ActivatorUtilities.GetServiceOrCreateInstance<IMyClass>(host.Services /*HOW TO INJECT MY INSTANCE OF mySpecialImpementation*/ );
    }

    internal void Show()
    {
        myClass.ShowInfo();
        myClassSpecial.ShowInfo();
    }
}

public interface IMyClass
{
    void ShowInfo();
}

public interface MyBaseInterface
{
    string GetInformation { get; }
}

public interface IMyInterface1 : MyBaseInterface
{
}
public interface IMyInterface2 : MyBaseInterface
{
}

public class MyInterface1Impl1 : IMyInterface1
{
    public string GetInformation => $"{nameof(MyInterface1Impl1)}";
}
public class MyInterface1Impl2 : IMyInterface2
{
    public string GetInformation => $"{nameof(MyInterface1Impl2)}";
}

public class MySpecialImpementation : IMyInterface2
{
    public string GetInformation => "MY SPECIAL STUFF";
}
1 Answers

In case someone else stumbles on the same issue, here is what helped me solve the issue link.

First I created this helper class:

public class DependencyHelper
{
    public static T CreateService<T>(IServiceProvider serviceProvider, object data)
    {
        if (serviceProvider == null) throw new ArgumentNullException(nameof(serviceProvider));
        var something = serviceProvider.GetRequiredService(typeof(T));
        var type = something.GetType();
        var psuChainDevice = (T)ActivatorUtilities.CreateInstance(serviceProvider, type, data);
        return psuChainDevice;
    }

    public static T? GetObjectOfType<T>(object parameters)
    {
        switch (parameters)
        {
            case null: throw new ArgumentNullException(nameof(parameters));
            case object[] arrayItems:
                var resultArrayItem = GetFirstMatchingObject<T>(arrayItems.ToList());
                return resultArrayItem;
            case List<object> listItems:
                var resultListItem = GetFirstMatchingObject<T>(listItems);
                return resultListItem;
            case object oneItem:
                var oneItemList = GetFirstMatchingObject<T>(new List<object> { oneItem });
                return oneItemList;
        }
    }

    private static T? GetFirstMatchingObject<T>(List<object> items)
    {
        var result = items.FirstOrDefault(item => item.GetType() == typeof(T));
        if (result is null) return default;
        return (T)result;
    }
}

and used it like this

var psuChainDevice = DependencyHelper.CreateService<IPsuChainDevice>(serviceProvider, someDeviceThatWasCreatedSomewhere);

the definition of the class (in this example PSUChainDevice) was done like this

    public class PSUChainDevice : IPsuChainDevice
{
  public PSUChainDevice()
  {
  }

  public PSUChainDevice(ISomething1 something1, ISomething2 something2, object deviceParameter)
  {
    var ftdiDevice = DependencyHelper.GetObjectOfType<FTDIDevice>(deviceParameter);
  }
}

and finally it was wired up as a transient device

        public static IServiceProvider CreateServiceProvider()
    {
        var provider = new ServiceCollection()
            .AddTransient<IPsuChainDevice, PSUChainDevice>()
            .BuildServiceProvider();
        return provider;
    }
Related