Created
February 11, 2017 22:22
-
-
Save thiagomajesk/bb493719674c57c6eec6975ca3fe7835 to your computer and use it in GitHub Desktop.
View Model Factories in ASP.NET Core with Mediator + IoC Extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FooController : Controller | |
{ | |
private readonly IViewFactory viewFactory; | |
public FooController(IViewFactory viewFactory) { this.viewFactory = viewFactory; } | |
public IActionResult Index() | |
{ | |
var viewModel = viewFactory.Create<CreateFooViewModel>(); | |
return View(viewModel); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface IViewFactory | |
{ | |
TView Create<TView>(); | |
TView Create<TInput, TView>(TInput input); | |
} | |
public class DefaultViewFactory : IViewFactory | |
{ | |
private readonly IServiceProvider provider; | |
public DefaultViewFactory(IServiceProvider provider) { this.provider = provider; } | |
public TView Create<TView>() | |
{ | |
var builder = provider.GetService(typeof(IViewBuilder<TView>)) as IViewBuilder<TView>; | |
return (builder != null ? builder.Build() : Activator.CreateInstance<TView>()); | |
} | |
public TView Create<TInput, TView>(TInput input) | |
{ | |
var builder = provider.GetService(typeof(IViewBuilder<TView, TInput>)) as IViewBuilder<TView, TInput>; | |
return (builder != null ? builder.Build(input) : (TView)Activator.CreateInstance(typeof(TView), input)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class ContainerExtensions | |
{ | |
public static IServiceCollection ConnectImplementations<TService>(this IServiceCollection services, Assembly assembly) where TService : class | |
{ | |
return services.ConnectImplementations(typeof(TService), assembly); | |
} | |
public static IServiceCollection ConnectImplementations(this IServiceCollection services, Type serviceType, Assembly assembly) | |
{ | |
if (!serviceType.IsInterface) throw new ArgumentException("Type must be an interface"); | |
var concreteTypes = assembly.ExportedTypes.Select(t => t.GetTypeInfo()).Where(ti => ti.IsClass && !ti.IsAbstract); | |
foreach (var type in concreteTypes) | |
{ | |
var interfaces = type.ImplementedInterfaces.Select(i => i.GetTypeInfo()).ToArray(); | |
foreach (var @interface in interfaces.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == serviceType)) | |
{ | |
services.AddTransient(@interface.AsType(), type.AsType()); | |
} | |
foreach (var @interface in interfaces.Where(i => !i.IsGenericType && i.IsAssignableFrom(serviceType))) | |
{ | |
services.AddTransient(@interface.AsType(), type.AsType()); | |
} | |
} | |
return services; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface IFoo | |
{ | |
string GetDescription(); | |
} | |
public class Foo : IFoo | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
public string GetDescription() => $"Id: {Id} | Name: {Name}"; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface IViewBuilder<TView> | |
{ | |
TView Build(); | |
} | |
public interface IViewBuilder<TView, TInput> | |
{ | |
TView Build(TInput input); | |
} | |
public class CreateFooViewBuilder : IViewBuilder<CreateFooViewModel> | |
{ | |
private readonly DatabaseContext context; | |
public CreateFooViewBuilder(DatabaseContext context) { this.context = context; } | |
public CreateFooViewModel Build() | |
{ | |
return new CreateFooViewModel { Id = 1, Name = "Foo" }; | |
} | |
} | |
public class EditFooViewBuilder : IViewBuilder<CreateFooViewModel, string> | |
{ | |
private readonly DatabaseContext context; | |
public EditFooViewBuilder(DatabaseContext context) { this.context = context; } | |
public CreateFooViewModel Build(string input) | |
{ | |
return new CreateFooViewModel { Id = 1, Name = input }; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CreateFooViewModel | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
} | |
public class EditFooViewModel | |
{ | |
public string Name { get; set; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void ConfigureServices(IServiceCollection services) | |
{ | |
// [...] | |
services.AddScoped(typeof(IViewFactory), typeof(DefaultViewFactory)); | |
services.ConnectImplementations(typeof(IFoo), Assembly.GetExecutingAssembly()); | |
services.ConnectImplementations(typeof(IViewBuilder<>), Assembly.GetExecutingAssembly()); | |
services.ConnectImplementations(typeof(IViewBuilder<,>), Assembly.GetExecutingAssembly()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment