Search code examples
c#dependency-injectionmvvmcross

MVVMCross dynamically construct generic IMvxLog<T> for dependency injection


I'm trying to get Mvx to work in the same way that Microsoft Logging works e.g. ILogger<T> via injection but getting stuck.

I've extended the interface:

public interface IMvxLog<T> : IMvxLog {

}

In my LoginViewModel I want to inject this:

public LoginViewModel(IMvxLog<LoginViewModel> loggger) { }

And then I figured I could dynamically construct by using the below in App.cs:

var logProvider = Mvx.IoCProvider.Resolve<IMvxLogProvider>();
Mvx.IoCProvider.LazyConstructAndRegisterSingleton(typeof(IMvxLog<>), () => logProvider.GetLogFor<>());

It doesn't work as I don't have a type argument to pass to the delegation.

Using the generic method group 'GetLogFor' requires 1 type arguments

How can this be done?


Solution

  • What you're doing there is not allowed, the way Mvx can register these kind of injections is by using open generics typeof(IFoo<>).

    You can do what you want by just wrapping the provider GetLogFor in the MvxLog<T> implementation and calls the same methods inside:

    public interface IMvxLog<T> : IMvxLog
    {
    }
    
    public class MvxLog<T> : IMvxLog<T>
    {
        private readonly IMvxLog _logImplementation;
    
        public MvxLog(IMvxLogProvider provider)
        {
            _logImplementation = provider.GetLogFor<T>();
        }
    
        public bool IsLogLevelEnabled(MvxLogLevel logLevel)
        {
            return _logImplementation.IsLogLevelEnabled(logLevel);
        }
    
        public bool Log(MvxLogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters)
        {
            return _logImplementation.Log(logLevel, messageFunc, exception, formatParameters);
        }
    }
    

    and then you just register it:

    Mvx.IoCProvider.RegisterType(typeof(IMvxLog<>), typeof(MvxLog<>));
    

    and use it like:

    public LoginViewModel(IMvxLog<LoginViewModel> loggger) 
    { 
        _logger = logger;    
    }
    

    HIH