63 lines
2.1 KiB
C#
63 lines
2.1 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace FlowScope.Container
|
|
{
|
|
public static class ReflectionFactoryBuilder
|
|
{
|
|
public static void RegisterType<TImplementation>(Container container)
|
|
{
|
|
if (container == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(container));
|
|
}
|
|
|
|
container.RegisterFactory(typeof(TImplementation), BuildFactory(typeof(TImplementation)));
|
|
}
|
|
|
|
public static void RegisterType<TInterface, TImplementation>(Container container)
|
|
where TImplementation : TInterface
|
|
{
|
|
if (container == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(container));
|
|
}
|
|
|
|
container.RegisterFactory(typeof(TInterface), BuildFactory(typeof(TImplementation)));
|
|
}
|
|
|
|
public static Func<Container, object> BuildFactory(Type implementationType)
|
|
{
|
|
if (implementationType == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(implementationType));
|
|
}
|
|
|
|
if (!Attribute.IsDefined(implementationType, typeof(InjectableAttribute)))
|
|
{
|
|
throw new InvalidOperationException($"{FormatType(implementationType)} must be marked with InjectableAttribute for reflection registration.");
|
|
}
|
|
|
|
var constructors = implementationType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
|
|
if (constructors.Length != 1)
|
|
{
|
|
throw new InvalidOperationException($"{FormatType(implementationType)} must declare exactly one public constructor.");
|
|
}
|
|
|
|
var constructor = constructors[0];
|
|
var parameters = constructor.GetParameters();
|
|
|
|
return container =>
|
|
{
|
|
var arguments = parameters
|
|
.Select(parameter => container.Resolve(parameter.ParameterType))
|
|
.ToArray();
|
|
return constructor.Invoke(arguments);
|
|
};
|
|
}
|
|
|
|
private static string FormatType(Type type) => type.FullName ?? type.Name;
|
|
}
|
|
}
|