In .Core project I have an interface for logging:
public interface ILogger
{
void Trace(string format, params object[] args);
.........
void Fatal(string format, params object[] args);
}
Which is used in a log service interface:
public interface ILogService
{
ILogger GetLogger(string name);
ILogger GetLogger(Type typeName);
ILogger GetLogger<T>();
}
In .Droid project that interface is implemented:
public class AndroidLogService : ILogService
{
public ILogger GetLogger(string name)
{
return new AndroidLogger(name);
}
public ILogger GetLogger(Type typeName)
{
return GetLogger(typeName.Name);
}
public ILogger GetLogger<T>()
{
return GetLogger(typeof(T));
}
}
In .Droid Setup.cs file AndroidLogService is registered:
Mvx.LazyConstructAndRegisterSingleton<ILogService, AndroidLogService>();
Mvx.LazyConstructAndRegisterSingleton<IFileService, AndroidFileService>();
and finally used in some file in .Droid project:
private readonly ILogger _logger;
public AndroidFileService(IContextService contextService, ILogService logService, IEncryptionService encryptionService)
{
_logger = logService.GetLogger<AndroidFileService>();
.......
}
Finally logs work like this:
_logger.Warn("Failed to retrieve logo. Error: {0}", ex);
My doubts and questions: AndroidFileService is never called with params that described above but from MvvmCross docs I've read that it's called Construction Injection
Ok, I understand this part but one thing is dark for me: Where ILogger implementation exists? I didn't find in the whole solution any part with something like
Mvx.RegisterType<ILogger , SomeLogger>();
How it can be? What a mechanism is used to register ILogger?
I found the answer.
I went inside AndroidLogService in Setup.cs:
public class AndroidLogService : ILogService
{
public ILogger GetLogger(string name)
{
return new AndroidLogger(name);
}
public ILogger GetLogger(Type typeName)
{
return GetLogger(typeName.Name);
}
public ILogger GetLogger<T>()
{
return GetLogger(typeof(T));
}
}
Then I went inside AndroidLogger:
using NLog;
using ILogger = ....Services.Support.ILogger;//from .Core project
namespace ....Android.Services.Support//from .Droid project
{
public class AndroidLogger : ILogger
{
private readonly NLog.ILogger _logger;
public AndroidLogger(string name)
{
_logger = LogManager.GetLogger(name);
}
.................
where I see that is used NLog which is built-in implementation of ILogger.
So, when the build was created for android I inserted this snippet in 2 files: one from .Core project and another from .Droid
_logger = logService.GetLogger<SomeViewModel>();
String name = logService.GetType().Name;
_logger.Debug("LogService name = {0} ", name);
which resulted for both cases as LogService name = AndroidLogService.
Before this check I thought that as .Core project doesn't have any reference to .Droid project, so, there are different implementations for them, but I was wrong: Interface implemented in .Droid/.iOs project also works for .Core project.