Could someone please show me how I register the following Factory in .NET 8?:
public class DefaultViewFactory : IViewFactory
{
private readonly IServiceProvider _serviceProvider;
public DefaultViewFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public TView CreateView<TView>()
{
var service = _serviceProvider.GetService<IViewBuilder<TView>>();
return service != null ? service.Build() : Activator.CreateInstance<TView>();
}
public TView CreateView<TInput, TView>(TInput input)
{
var service = _serviceProvider.GetService<IViewBuilder<TInput, TView>>();
if (service != null)
{
return service.Build(input);
}
return (TView)Activator.CreateInstance(typeof(TView), input)!;
}
}
I’ve added the following code to the Program.cs file:
serviceCollection.AddTransient<IViewFactory, DefaultViewFactory>();
Previously using StructureMap, the following would be used:
configurationExpression.Scan(assemblyScanner =>
{
assemblyScanner.TheCallingAssembly();
assemblyScanner.ConnectImplementationsToTypesClosing(typeof(IViewBuilder<>));
assemblyScanner.ConnectImplementationsToTypesClosing(typeof(IViewBuilder<,>));
})
Could someone please advise an alternative implementation?
I have added the IViewBuilder for reference:
public interface IViewBuilder<out TView>
{
TView Build();
}
public interface IViewBuilder<in TInput, out TView>
{
TView Build(TInput input);
}
>Solution :
.NET (Core) build-in DI does not support assembly scanning and matching closed generic types.
If you have a single open generic implementation then you can register it as open generic:
services.AddTransient(typeof(IViewBuilder<>), typeof(SomeGenericViewBuilder<>));
services.AddTransient(typeof(IViewBuilder<,>), typeof(SomeGenericViewBuilder<,>));
If you have different types implementing the interface then you can:
-
Register them manually:
services.AddTransient(typeof(IViewBuilder<SomeView>), typeof(SomeViewBuilder)); // ... -
Write assembly scanning code yourself (using reflection APIs)
-
Use some library like
Scrutor(not tested):var collection = new ServiceCollection(); collection.Scan(scan => scan // We start out with all types in the assembly .FromAssemblyOf<ViewBuildersAssemblyTypeLandmark>() // Generic interfaces are also supported too .AddClasses(classes => classes.AssignableTo(typeof(IViewBuilder<>))) .AsImplementedInterfaces() // And you scan generics with multiple type parameters .AddClasses(classes => classes.AssignableTo(typeof(IViewBuilder<,>))) .AsImplementedInterfaces()); -
Look into replacing default service container with one which supports needed functionality