Search code examples
c#asp.net-web-apidependency-injectiondryioc

Using DryIoc with a dependency and primitive values


I am registering an implementation to be created for an interface. This implementations constructor has three paramaters:

public ProfileImageService(ISqlConnection connection, string localStorageLocation, string serverPath)

I have already registered the ISqlConnection like this:

c.Register<Data.ISqlConnection, Data.TsqlConnection>(setup: Setup.With(openResolutionScope: true));

However when I register the ProfileImageService like this:

c.Register<Data.Services.Profile.IImageService, Data.Services.Profile.ProfileImageService>(Made.Of(() => new Data.Services.Profile.ProfileImageService(Arg.Index<Data.ISqlConnection>(0), Arg.Index<string>(1), Arg.Index<string>(2)), requestIgnored =>c.Resolve<Data.ISqlConnection>(), requestIgnored => localImageStoragePath, requestIgnored => localImageUrl));

I get the following error:

Message=State is required to use (probably to inject) item Abc.Data.TsqlConnection. To enable item use you may specify container.With(rules => rules.WithItemToExpressionConverter(YOUR_ITEM_TO_EXPRESSION_DELEGATE)).

I have read this SpecifyDependencyAndPrimitiveValues and tried to rework it like they have but their example only shows it with primitives or with dependancies, not both and I can't find the syntax where they mix without compile errors. Can anyone give me some guidance on how to register this instance, specifying the values for the two strings and the value for the dependency?


Solution

  • Here is how you do it (using latest DryIoc v2.10.6): you don't need to specify c.Resolve<ISqlConnection>() in parameter, just use Arg.Of<ISqlConnection>():

    using System;
    using DryIoc;
    
    public class Program
    {
        public static void Main()
        {
            var c = new Container();
    
            var localImageStoragePath = "a";
            var localImageUrl = "b";
    
            c.Register<ISqlConnection, TsqlConnection>();
            c.Register<IImageService, ProfileImageService>(
                Made.Of(() => new ProfileImageService(
                    Arg.Of<ISqlConnection>(), 
                    Arg.Index<string>(0), 
                    Arg.Index<string>(1)), 
                    _ => localImageStoragePath, 
                    _ => localImageUrl));
    
            var imgService = c.Resolve<IImageService>();
    
            Console.WriteLine(imgService);
        }
    
        public interface IImageService {}
    
        public class ProfileImageService: IImageService
        {
            public ProfileImageService(ISqlConnection conn, string a, string b) {}
    
        }
    
        public interface ISqlConnection {}
    
        public class TsqlConnection : ISqlConnection {} 
    }
    

    Or even better, if your string arguments are not supposed to be changed:

        c.Register<IImageService, ProfileImageService>(
            Made.Of(() => new ProfileImageService(
                Arg.Of<ISqlConnection>(), 
                localImageStoragePath, 
                localImageUrl)));
    

    Here is the live proof.