in sources/Google.Solutions.IapDesktop.Core/ObjectModel/ServiceRegistry.cs [75:172]
private object CreateInstance(Type serviceType)
{
//
// Check for ctor(IServiceProvider).
//
var constructorWithServiceProvider = serviceType.GetConstructor(
BindingFlags.Public | BindingFlags.Instance,
null,
new[] { typeof(IServiceProvider) },
null);
if (constructorWithServiceProvider != null)
{
return Activator.CreateInstance(serviceType, (IServiceProvider)this);
}
//
// Check for ctor(IServiceCategoryProvider).
//
var constructorWithServiceCategoryProvider = serviceType.GetConstructor(
BindingFlags.Public | BindingFlags.Instance,
null,
new[] { typeof(IServiceCategoryProvider) },
null);
if (constructorWithServiceCategoryProvider != null)
{
return Activator.CreateInstance(serviceType, (IServiceCategoryProvider)this);
}
//
// Check other constructors and see if there is one for which all
// parameters can be bound to a service. Analyze the one with the most
// parameters first.
//
bool IsSupportedConstructorArgumentType(Type t)
{
if (t == serviceType)
{
// Don't allow recursion
return false;
}
if (IsServiceRegistered(t))
{
return true;
}
else if (IsDecorator(t) && t.GetGenericArguments().All(IsServiceRegistered))
{
return true;
}
else
{
return false;
}
}
foreach (var constructor in serviceType.GetConstructors()
.OrderByDescending(c => c.GetParameters().Length))
{
if (constructor
.GetParameters()
.Select(p => p.ParameterType)
.All(t => IsSupportedConstructorArgumentType(t)))
{
// We have services for all parameters.
var parameterValues = constructor
.GetParameters()
.Select(p => GetService(p.ParameterType))
.ToArray();
return Activator.CreateInstance(
serviceType,
parameterValues);
}
else
{
#if DEBUG
Debug.WriteLine($"ServiceRegistry: {serviceType} has an unsuitable ctor: {constructor}");
foreach (var t in constructor
.GetParameters()
.Select(p => p.ParameterType)
.Where(t => !IsSupportedConstructorArgumentType(t))
.ToList())
{
Debug.WriteLine($" > Unsupported argument type: {t}");
}
#endif
//
// There is at least one parameter that we do not
// have a suitable service for.
//
}
}
throw new UnknownServiceException(
$"Class {serviceType.Name} lacks a suitable constructor to serve as service");
}