instantiate ValidatorFactory with unity ioc - c#

I am having some trouble trying to integrate FluentValidation with Unity.
I have a factory class
public class UnityValidatorFactory : FluentValidation.ValidatorFactoryBase
{
private readonly IUnityContainer _container;
public UnityValidatorFactory()
{
_container = null;
}
public UnityValidatorFactory(IUnityContainer container)
{
_container = container;
}
public override FluentValidation.IValidator CreateInstance(Type validatorType)
{
return _container.Resolve(validatorType) as FluentValidation.IValidator;
}
}
The problem is that it won't instantiate in the data class
public class Payment : IValidatableObject
{
private readonly IValidator _validator = new PaymentValidator();
public string paymentType { get; set; }
//etc
public Payment(IValidatorFactory validatorFactory)
{
**//ValidatorFactory is always null!**
_validator = validatorFactory.GetValidator(typeof(Payment));
}
}
This is the code I am trying to use to register the factory class with unity
container.RegisterType<IValidatorFactory, UnityValidatorFactory>(new ContainerControlledLifetimeManager());
However the factory is always null. Any idea what I am doing wrong?

My suggestion would be the next.
Create all your validators and implement the next interface, name it as: IModelValidator
public interface IModelValidator
{
}
//example of a validator class
public class MyModelValidator : AbstractValidator<MyModel>, IModelValidator
{
public MyModelValidator ()
{
CascadeMode = CascadeMode.StopOnFirstFailure;
RuleFor(x => x.yourField)
.NotNull()
.NotEmpty()
.WithMessage("You need to enter yourField");
}
}
//this is to register all your interfaces on the container
void RegisterValidators(IUnityContainer container)
{
var type = typeof(IValidator<>);
var validators = AssemblyScanner.FindValidatorsInAssemblyContaining<IModelValidator>();
validators.ForEach(validator => container.RegisterType(validator.InterfaceType, validator.ValidatorType));
}
//Integrating with MVC, this should be do in your Global.asax when you create your container
public static ConfigureFluentValidation(IUnityContainer container)
{
var fluentValidationModelValidatorProvider = new FluentValidationModelValidatorProvider(new UnityValidationFactory(container));
//disables the implicit required validator being added for both the DataAnnotationsModelProvider, as well as the FluentValidationModelValidatorProvider.
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
fluentValidationModelValidatorProvider.AddImplicitRequiredValidator = false;
//adds the new model validator provider to the list of model validator providers used by the MVC framework.
ModelValidatorProviders.Providers.Add(fluentValidationModelValidatorProvider);
}
Now in your controller method when you post the information to be validated you will see if you leave yourField empty that ModelState.IsValid has a false value

Related

How to resolve an interface and use it in the class using Autofac

I'm trying to resolve an interface that I registered in Autofac but it seems to be not working. There is
nullreferenceexception.
Class where I register the inferface :
public void RegisterAutofac(HttpConfiguration config)
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
(...)
builder.RegisterType<ApiFileTester>().As<IApiFlTester>().InstancePerRequest();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
Then I want to use it in a class :
public class ApiFileSendingController : ApiClientBase
{
private readonly IApiFlTester _apiFileTester;
public ApiFileSendingController(DTO dto, IApiFlTester tester) : base(dto)
{
_tester = tester;
}
public void Send(List<AftInvFileDTO> filesToSendRetry = null)
{
_apiFileTester.RegisterTestingMethods();
}
}
Then in some other class:
DTO dto = new DTO(); //some configuration here
ApiFileSendingController sender = new ApiFileSendingController(dto, null);
sender.Send();
There is a problem here because my interface is null. I've tried to pass it like this:
ApiFileSendingController sender = new ApiFileSendingController(dto,
null);
but it's null and it's completely reasonable (I am passing the null).
IS it possible to configure optional parameter or something? I'd like to have this interface resolved automatically by autofac, not manually.
I don't seem to have a problem resolving your class. Technically it's impossible to really answer your question since the code won't even compile and it appears you have a ton of missing autofac registrations.
Working Example.
// #nuget: Autofac
using System;
using Autofac;
public class Program
{
private static IContainer _container;
public static void Main()
{
RegisterAutofac();
using (var httpRequestScope = _container.BeginLifetimeScope("AutofacWebRequest"))
{
var apiController = httpRequestScope.Resolve<ApiFileSendingController>();
Console.WriteLine(apiController._apiFileTester);
}
}
public static void RegisterAutofac()
{
var builder = new ContainerBuilder();
//builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<ApiFileTester>().As<IApiFlTester>().InstancePerLifetimeScope();
builder.RegisterType<ApiFileSendingController>().AsSelf();
builder.RegisterType<DTO>().AsSelf();
_container = builder.Build();
}
public class ApiFileSendingController : ApiClientBase
{
public readonly IApiFlTester _apiFileTester;
public ApiFileSendingController(DTO dto, IApiFlTester tester): base (dto)
{
_apiFileTester = tester;
}
}
public interface IApiFlTester { }
public class ApiFileTester : IApiFlTester { }
public class ApiClientBase
{
public ApiClientBase(DTO dto)
{
}
}
public class DTO { }
}
You have misconception at Autofac DI, most of the DI frameworks are good at creating instances for you, via constructor injection and property injection you will get the instance with their dependencies automatically wired up.
Your constructor contains DTO instance which you will provide during runtime, Autofac will not resolve that since you had not declare it to the DI container during ConfigureServices cycle.
You might need to giving up using Autofac in this case to get the freedom of creating controller instance at your own code, you will need to get the concrete class instance from Reflection instead. The abstraction / implementation isolation is still there via this approach.
public class ApiFileSendingController : ApiClientBase
{
private readonly IApiFlTester _apiFileTester;
public ApiFileSendingController(DTO dto, IApiFlTester tester) : base(dto)
{
if (tester is null)
_tester = GetApiTesterViaReflection();
else
_tester = tester;
}
public ApiFileSendingController(DTO dto) : base(dto)
{
_apiFileTester = GetApiTesterViaReflection();
}
public void Send(List<AftInvFileDTO> filesToSendRetry = null)
{
_apiFileTester.RegisterTestingMethods();
}
private IApiFlTester GetApiTesterViaReflection()
{
Type type = typeof(IApiFlTester).Assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IApiFlTester))).FirstOrDefault();
return Activator.CreateInstance(type) as IApiFlTester;
}
}

Instantiating types using AutoMapper with a DI container

Please see the code below:
public class Test : ITest
{
public ITest2 _iTest2;
public int _id;
public string _name;
public Test(ITest2 test2)
{
_iTest2 = test2;
}
}
public interface ITest
{
}
public class Test2 : ITest2
{
}
public interface ITest2
{
}
public class Test3 : ITest3
{
public int _id;
public string _name;
}
public interface ITest3
{
}
I have the following in my Global.asax:
Mapper.Initialize(m =>
{
m.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
});
I can map the types in my client app doing this:
cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
How can I map the types using Castle Windsor instead of having to use the new keyword for Test and Test2?
I read another answer and someone suggested doing this:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn(typeof(IValueResolver<,,>)));
// container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn<IValueResolver>());
container.Register(Types.FromThisAssembly().BasedOn<Profile>().WithServiceBase());
var profiles = container.ResolveAll<Profile>();
// Add your list of profiles to the mapper configuration here
Mapper.Initialize(m => {
m.ConstructServicesUsing(container.Resolve);
profiles.ToList().ForEach(p => m.AddProfile(p));
});
// I'm not sure about this as I haven't used AutoMapper for a while,
// but I assume you want to resolve the static mapper instance
container.Register(Component.For<IMapper>().Instance(Mapper.Instance));
}
Do I have to do this:
cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
or should AutoMapper be able to map the types using this:
cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>()
In order to get AutoMapper to use Windsor to create the target type, you need to configure two things:
Tell AutoMapper to construct services using Windsor
Tell AutoMapper (per-mapping) to actually use the above configuration
var container = new WindsorContainer();
Mapper.Initialize(m =>
{
m.ConstructServicesUsing(container.Resolve);
m.CreateMap<Test3, ITest>().ConstructUsingServiceLocator(); // This is important!
});
container.Register(Component.For<ITest>().ImplementedBy<Test>());
container.Register(Component.For<ITest2>().ImplementedBy<Test2>());
container.Register(Component.For<ITest3>().ImplementedBy<Test3>());
var test3 = new Test3();
var test1 = Mapper.Instance.Map<Test3, ITest>(test3);
For anyone requiring this using xamarin 3.6, prism 7.1 and automapper 8.1, this is what worked for me.
In the App.xml.cs file
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
/// other registrations ...
containerRegistry.RegisterSingleton<IMapperProvider, MapperProvider>();
containerRegistry.RegisterInstance(typeof(IMapper), GetMapper(containerRegistry));
}
/// <summary>
/// This function required in order for injection into custom automapper resolvers
/// </summary>
private IMapper GetMapper(IContainerRegistry container)
{
var mp = container.GetContainer().Resolve<IMapperProvider>(new[] { container });
return mp.GetMapper();
}
The mapper provider looks like this:
public class MapperProvider : IMapperProvider
{
private readonly IContainerRegistry _container;
public MapperProvider(IContainerRegistry container)
{
_container = container;
}
public IMapper GetMapper()
{
var config = new MapperConfiguration(cfg =>
{
cfg.ConstructServicesUsing(t => _container.GetContainer().Resolve(t));
// any custom profile statement such as
cfg.AddProfile<MappingSourcesProfile>();
// ....
});
return config.CreateMapper();
}
}
Now my custom resolvers works, for example:
public class BarcodesResolver : IValueResolver<repo.Book, Book, List<Barcode>>
{
private readonly IMapper _mapper;
public BarcodesResolver(IMapper mapper)
{
_mapper = mapper;
}
public List<Barcode> Resolve(repo.Book source, Book destination, List<Barcode> destMember, ResolutionContext context)
{
repo.BookAttributes groupedAttribs = JsonConvert.DeserializeObject<repo.BookAttributes>(source.BookAttributes);
return _mapper.Map<List<repo.Barcode>, List<Barcode>>(groupedAttribs.Barcodes);
}
}
The hard parts to work out here were how to specify that the containerRegistry needed to be passed into the constructor of the MapperProvider. There may be a better way of doing this but at least this works.
Also arriving at the line cfg.ConstructServicesUsing(t => _container.GetContainer().Resolve(t)); was quite obscure as there seem to be few examples out there.

How can I pass a runtime parameter as part of the dependency resolution?

I need to be able to pass a connection string into some of my service implementations. I am doing this in the constructor. The connection string is configurable by user will be added the ClaimsPrincipal as a Claim.
All fine so far.
Unfortunately, I also want to be able to use the dependency injection features in ASP.NET Core to the fullest and resolve the service implementation though DI.
I have a POC implmentation:
public interface IRootService
{
INestedService NestedService { get; set; }
void DoSomething();
}
public class RootService : IRootService
{
public INestedService NestedService { get; set; }
public RootService(INestedService nestedService)
{
NestedService = nestedService;
}
public void DoSomething()
{
// implement
}
}
public interface INestedService
{
string ConnectionString { get; set; }
void DoSomethingElse();
}
public class NestedService : INestedService
{
public string ConnectionString { get; set; }
public NestedService(string connectionString)
{
ConnectionString = connectionString;
}
public void DoSomethingElse()
{
// implement
}
}
These services have been registered during startup and INestedService has been added the constructor of a controller.
public HomeController(INestedService nestedService)
{
NestedService = nestedService;
}
As expected, I get the error Unable to resolve service for type 'System.String' while attempting to activate 'Test.Dependency.Services.NestedService'.
What are my options here?
To pass a runtime parameter not known at the start of the application, you have to use the factory pattern. You have two options here:
factory class (similar to how IHttpClientFactory is implemented)
public class RootService : IRootService
{
public RootService(INestedService nested, IOtherService other)
{
// ...
}
}
public class RootServiceFactory : IRootServiceFactory
{
// in case you need other dependencies, that can be resolved by DI
private readonly IServiceProvider services;
public RootServiceFactory(IServiceProvider services)
{
this.services = services;
}
public IRootService CreateInstance(string connectionString)
{
// instantiate service that needs runtime parameter
var nestedService = new NestedService(connectionString);
// note that in this example, RootService also has a dependency on
// IOtherService - ActivatorUtilities.CreateInstance will automagically
// resolve that dependency, and any others not explicitly provided, from
// the specified IServiceProvider
return ActivatorUtilities.CreateInstance<RootService>(services,
new object[] { nestedService, });
}
}
and inject IRootServiceFactory instead of your IRootService
IRootService rootService = rootServiceFactory.CreateInstance(connectionString);
factory method
services.AddTransient<Func<string,INestedService>>((provider) =>
{
return new Func<string,INestedService>(
(connectionString) => new NestedService(connectionString)
);
});
and inject the factory method into your service instead of INestedService
public class RootService : IRootService
{
public INestedService NestedService { get; set; }
public RootService(Func<string,INestedService> nestedServiceFactory)
{
NestedService = nestedServiceFactory("ConnectionStringHere");
}
public void DoSomething()
{
// implement
}
}
or resolve it per call
public class RootService : IRootService
{
public Func<string,INestedService> NestedServiceFactory { get; set; }
public RootService(Func<string,INestedService> nestedServiceFactory)
{
NestedServiceFactory = nestedServiceFactory;
}
public void DoSomething(string connectionString)
{
var nestedService = nestedServiceFactory(connectionString);
// implement
}
}
Simple configuration
public void ConfigureServices(IServiceCollection services)
{
// Choose Scope, Singleton or Transient method
services.AddSingleton<IRootService, RootService>();
services.AddSingleton<INestedService, NestedService>(serviceProvider=>
{
return new NestedService("someConnectionString");
});
}
With appSettings.json
If you decide to hide your connection string inside appSettings.json, e.g:
"Data": {
"ConnectionString": "someConnectionString"
}
Then provided that you've loaded your appSettings.json in the ConfigurationBuilder (usually located in the constructor of the Startup class), then your ConfigureServices would look like this:
public void ConfigureServices(IServiceCollection services)
{
// Choose Scope, Singleton or Transient method
services.AddSingleton<IRootService, RootService>();
services.AddSingleton<INestedService, NestedService>(serviceProvider=>
{
var connectionString = Configuration["Data:ConnectionString"];
return new NestedService(connectionString);
});
}
With extension methods
namespace Microsoft.Extensions.DependencyInjection
{
public static class RootServiceExtensions //you can pick a better name
{
//again pick a better name
public static IServiceCollection AddRootServices(this IServiceCollection services, string connectionString)
{
// Choose Scope, Singleton or Transient method
services.AddSingleton<IRootService, RootService>();
services.AddSingleton<INestedService, NestedService>(_ =>
new NestedService(connectionString));
}
}
}
Then your ConfigureServices method would look like this
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration["Data:ConnectionString"];
services.AddRootServices(connectionString);
}
With options builder
Should you need more parameters, you can go a step further and create an options class which you pass to RootService's constructor. If it becomes complex, you can use the Builder pattern.
I devised this little pattern to help me resolve objects that require runtime parameters ,but also have dependencies which the DI container is able to resolve - I implemented this using the MS DI Container for a WPF App.
I already had a Service Locator (yes I know its a code smell - but I attempt to resolve that by the end of the example) that I used in specific scenarios to get access to objects in the DIC:
public interface IServiceFactory
{
T Get<T>();
}
Its implementation takes a func<> in the constructor to decouple the fact it relies on MS DI.
public class ServiceFactory : IServiceFactory
{
private readonly Func<Type, object> factory;
public ServiceFactory(Func<Type, object> factory)
{
this.factory = factory;
}
// Get an object of type T where T is usually an interface
public T Get<T>()
{
return (T)factory(typeof(T));
}
}
This was created in the composition root like so:
services.AddSingleton<IServiceFactory>(provider => new ServiceFactory(provider.GetService));
This pattern was extended to not only 'Get' objects of type T, but 'Create' objects of type T with parameters P:
public interface IServiceFactory
{
T Get<T>();
T Create<T>(params object[] p);
}
The implementation took another func<> to decouple the creation mechanism:
public class ServiceFactory : IServiceFactory
{
private readonly Func<Type, object> factory;
private readonly Func<Type, object[], object> creator;
public ServiceFactory(Func<Type, object> factory, Func<Type, object[], object> creator)
{
this.factory = factory;
this.creator = creator;
}
// Get an object of type T where T is usually an interface
public T Get<T>()
{
return (T)factory(typeof(T));
}
// Create (an obviously transient) object of type T, with runtime parameters 'p'
public T Create<T>(params object[] p)
{
IService<T> lookup = Get<IService<T>>();
return (T)creator(lookup.Type(), p);
}
}
The creation mechanism for the MS DI container is in the ActivatorUtilities extensions, here's the updated composition root:
services.AddSingleton<IServiceFactory>(
provider => new ServiceFactory(
provider.GetService,
(T, P) => ActivatorUtilities.CreateInstance(provider, T, P)));
Now that we can create objects the problem becomes we have no way of determining the type of object we need without the DI container actually creating an object of that type, which is where the IService interface comes in:
public interface IService<I>
{
// Returns mapped type for this I
Type Type();
}
This is used to determine what type we are trying to create, without actually creating the type, its implementation is:
public class Service<I, T> : IService<I>
{
public Type Type()
{
return typeof(T);
}
}
So to pull it all together, in your composition root you can have objects that don't have runtime parameters which can be resolved by 'Get' and ones which do resolved by 'Create' e.g.:
services.AddSingleton<ICategorySelectionVM, CategorySelectionVM>();
services.AddSingleton<IService<ISubCategorySelectionVM>, Service<ISubCategorySelectionVM, SubCategorySelectionVM>>();
services.AddSingleton<ILogger, Logger>();
The CategorySelectionVM has only dependencies that can be resolved via the DIC:
public CategorySelectionVM(ILogger logger) // constructor
And this can be created by anyone with a dependency on the service factory like:
public MainWindowVM(IServiceFactory serviceFactory) // constructor
{
}
private void OnHomeEvent()
{
CurrentView = serviceFactory.Get<ICategorySelectionVM>();
}
Where as the SubCategorySelectionVM has both dependencies that the DIC can resolve, and dependencies only known at runtime:
public SubCategorySelectionVM(ILogger logger, Category c) // constructor
And these can be created like so:
private void OnCategorySelectedEvent(Category category)
{
CurrentView = serviceFactory.Create<ISubCategorySelectionVM>(category);
}
Update : I just wanted to add a little enhancement which avoided using the service factory like a service locator, so I created a generic service factory which could only resolve objects of type B:
public interface IServiceFactory<B>
{
T Get<T>() where T : B;
T Create<T>(params object[] p) where T : B;
}
The implementation of this depends on the original service factory which could resolve objects of any type:
public class ServiceFactory<B> : IServiceFactory<B>
{
private readonly IServiceFactory serviceFactory;
public ServiceFactory(IServiceFactory serviceFactory)
{
this.serviceFactory = serviceFactory;
}
public T Get<T>() where T : B
{
return serviceFactory.Get<T>();
}
public T Create<T>(params object[] p) where T : B
{
return serviceFactory.Create<T>(p);
}
}
The composition root adds the original service factory for all the generic typed factories to depend on, and any of the typed factories:
services.AddSingleton<IServiceFactory>(provider => new ServiceFactory(provider.GetService, (T, P) => ActivatorUtilities.CreateInstance(provider, T, P)));
services.AddSingleton<IServiceFactory<BaseVM>, ServiceFactory<BaseVM>>();
Now our main view model can be restricted to creating only objects that derive from BaseVM:
public MainWindowVM(IServiceFactory<BaseVM> viewModelFactory)
{
this.viewModelFactory = viewModelFactory;
}
private void OnCategorySelectedEvent(Category category)
{
CurrentView = viewModelFactory.Create<SubCategorySelectionVM>(category);
}
private void OnHomeEvent()
{
CurrentView = viewModelFactory.Get<CategorySelectionVM>();
}
I know this is a bit old but thought i'd give my input since there is a easier way to do this in my opinion. This doesn't cover all the cases as shown in other posts. But this is a easy way of doing it.
public class MySingleton {
public MySingleton(string s, int i, bool b){
...
}
}
No lets create a service extention class to add easier and keep it neet
public static class ServiceCollectionExtentions
{
public static IServiceCollection RegisterSingleton(this IServiceCollection services, string s, int i, bool b) =>
services.AddSingleton(new MySingleton(s, i, b));
}
Now to call it from startup
services.RegisterSingleton("s", 1, true);
IMHO, follow the options pattern. Define a strong type to hold your connection string, then an IConfigureOptions<T> to configure it from your user claim.
public class ConnectionString {
public string Value { get; set; }
}
public class ConfigureConnection : IConfigureOptions<ConnectionString> {
private readonly IHttpContextAccessor accessor;
public ConfigureConnection (IHttpContextAccessor accessor) {
this.accessor = accessor;
}
public void Configure(ConnectionString config) {
config.Value = accessor.HttpContext.User ...
}
}
public class NestedService {
...
public NestedService(IOptions<ConnectionString> connection) {
ConnectionString = connection.Value.Value;
}
...
}
Further to #Tseng's extremely helpful answer, I found I could also adapt it to use delegates:
public delegate INestedService CreateNestedService(string connectionString);
services.AddTransient((provider) => new CreateNestedService(
(connectionString) => new NestedService(connectionString)
));
Implemented in RootService in the same way #Tseng suggested:
public class RootService : IRootService
{
public INestedService NestedService { get; set; }
public RootService(CreateNestedService createNestedService)
{
NestedService = createNestedService("ConnectionStringHere");
}
public void DoSomething()
{
// implement
}
}
I prefer this approach for cases where I need an instance of a factory in a class, as it means I can have a property of type CreateNestedService rather than Func<string, INestedService>.

Constructor dependency injection via unity with parameters from HttpContext

We're using domain to customize how our application behaves. I'll illustrate it on example:
// default behavior
public class CoreService : IService {
public virtual string Hello { get { return "Hello"; } }
public virtual string FavouriteDrink { get { return "Water"; } }
}
// german.site.com
public class GermanService : CoreService {
public override string Hello { get { return "Gutten tag"; } }
public override string FavouriteDrink { get { return "Beer"; } }
}
// usa.site.com
public class UsaService : CoreService {
public override string FavouriteDrink { get { return "Cofee"; } }
}
Services are bootstrapped as follow:
var container = new UnityContainer();
container.RegisterType<IService, CoreService>();
container.RegisterType<IService, GermanService>("german.site.com");
container.RegisterType<IService, UsaService>("usa.site.com");
I use Unity to bootstrap mvc controllers. IE:
public class HomeController : Controller {
private IService m_Service;
// contructor dependency injection magic - this resolves into "CoreService"
public HomeController([Dependency]IService service) {
if (service == null) {
throw new ArgumentNullException("service");
}
m_Service = service;
}
}
Is there a way how to change unity resolution so it'll take domain into account ? Right now I ended up with
public class HomeController : Controller {
private IService m_Service;
// contructor dependency injection magic - a lot less magical
public HomeController() {
m_Service = DomainServiceLocator.Retrieve<IService>();
}
}
Support classes:
public static class DomainServiceLocator {
private static UnityContainerAdapter adapter;
public static T Retrieve<T>() {
string domain = HttpContext.Current.Request.Url.Host;
if (adapter.IsServiceRegistered(typeof(T), domain)) {
return adapter.Resolve<T>(domain);
}
return adapter.Resolve<T>();
}
}
public class QueryableContainerExtension : UnityContainerExtension {
private List<RegisterInstanceEventArgs> registeredInstances = new List<RegisterInstanceEventArgs>();
private List<RegisterEventArgs> registeredTypes = new List<RegisterEventArgs>();
protected override void Initialize() {
this.Context.Registering += (sender, e) => { this.registeredTypes.Add(e); };
this.Context.RegisteringInstance += (sender, e) => { this.registeredInstances.Add(e); };
}
public bool IsServiceRegistered(Type service, string name) {
return registeredTypes.FirstOrDefault(e => e.TypeFrom == service && e.Name == name) != null
|| registeredInstances.FirstOrDefault(e => e.RegisteredType == service && e.Name == name) != null;
}
}
public class UnityContainerAdapter {
private readonly QueryableContainerExtension queryableContainerExtension;
private readonly IUnityContainer unityContainer;
public UnityContainerAdapter()
: this(new UnityContainer()) {
}
public UnityContainerAdapter(IUnityContainer unityContainer) {
this.unityContainer = unityContainer;
// adding extensions to unity container
this.queryableContainerExtension = new QueryableContainerExtension();
unityContainer.AddExtension(this.queryableContainerExtension);
}
public T Resolve<T>(string name) {
return unityContainer.Resolve<T>(name);
}
public T Resolve<T>() {
return unityContainer.Resolve<T>();
}
public bool IsServiceRegistered(Type service, string name) {
return this.queryableContainerExtension.IsServiceRegistered(service, name);
}
}
I like to use an injection factory in these scenarios when resolving something at runtime. Essentially you're resolving your type via the domain name:
So in your composition root you could register like this:
container.RegisterType<Func<string, IService>>
(
new InjectionFactory(c => new Func<string, IService>(name => c.Resolve<IService>(name)))
);
Then in your HomeController you can inject the delegate
public class HomeController
{
private readonly Func<string,IService> _serviceFactory;
public HomeController(Func<string, IService> serviceFactory)
{
if(serviceFactory==null)
throw new ArgumentNullException("serviceFactory");
this._serviceFactory= serviceFactory;
}
public void DoSomethingWithTheService()
{
var domain = this.HttpContext.Uri.Host;
var service = this._serviceFactory(domain);
var greeting = service.Hello;
}
}
```
This is then still unit testable and you have not leaked the DI contain implementation outside of "composition root".
Also.. should CoreService be abstract to avoid direct instantiation of it?
Below is the solution I ended up with - it is based on #Spencer idea. I've created a factory, default implementation to the factory has a reference to DI container itself (IUnityContainer in my case), so it can perform the resolution based on domain once it is asked to. It is also more "modern friendly" since in current generation of ASP.NET (ASP.NET CORE) there is no such thing as magic singleton providing current HttpContext and DI is hard coded into the framework.
public interface IFactory<T>
{
T Retrieve(string domain);
}
internal sealed class Factory<T> : IFactory<T>
{
private readonly IUnityContainer _container;
public Factory(IUnityContainer container)
{
_container = container;
}
public T Resolve(string domain)
{
// this is actually more complex - we have chain inheritance here
// for simplicity assume service is either registered for given
// domain or it throws an error
return _container.Resolve<T>(domain);
}
}
// bootstrapper
var container = new UnityContainer();
container.RegisterType<IService, CoreService>();
container.RegisterType<IService, GermanService>("german.site.com");
container.RegisterType<IService, UsaService>("usa.site.com");
container.RegisterInstance<IFactory<IService>>(new Factory<IService>(container));
And the home controller looks like
public class HomeController : Controller {
private IFactory<IService> m_Factory;
public HomeController(IFactory<IService> factory) {
m_Factory = factory;
}
private void FooBar() {
var service = m_Factory.Retrieve(this.HttpContext.Uri.Host);
var hello = service.Hello;
}
}
Its also a worth mentioning that - as I'm lazy - I've build a system of decorative attributes like
[Domain("german.site.com")]
public class GermanService : IService { ... }
[DomainRoot]
public class CoreService : IService { ... }
[Domain("usa.site.com")]
public class UsaService : CoreService { ... }
So the bootstrapping is done automatically across all types in given assembly. But that part is a bit lengthy - if anyone is interested I can post it on github.

FluentValidation as a service

I'm using FluentValidation 2 for validating some entities. I'd like to create an IValidationService that I can pass into other services to allow them to perform validation. I'd like to expose it like this:
public interface IValidationEngine
{
IEnumerable<ValidationError> Validate<T>(T entity);
}
Where ValidationError is a class that encapsulates my validation errors. Ideally, I'd like to not have to expose a specific validator to one of my services (such as OrderValidator). I'd like the validation service be capable of constructing/finding the correct validator. Does FV have anything built in for locating a validator for a specific type (and it internally caches)? Or, do I have to go the IValidatorFactory route and then wire each validator with my IoC container?
I've managed to solve this with the IValidatorFactory method. I'm using Ninject, so specific IoC details below would need to be changed.
public interface IValidationService
{
IEnumerable<ValidationError> Validate<T>(T entity)
where T : class;
}
public class FluentValidationService : IValidationService
{
private readonly IValidatorFactory validatorFactory;
public FluentValidationService(IValidatorFactory validatorFactory)
{
this.validatorFactory = validatorFactory;
}
public IEnumerable<ValidationError> Validate<T>(T entity)
where T : class
{
var validator = this.validatorFactory.GetValidator<T>();
var result = validator.Validate(entity);
return result.Errors.Select(e => new ValidationError(e.PropertyName, e.ErrorMessage));
}
}
// Then implement FV's IValidatorFactory:
public class NinjectValidatorFactory : ValidatorFactoryBase
{
private readonly IKernel kernel;
public NinjectValidatorFactory(IKernel kernel)
{
this.kernel = kernel;
}
public override IValidator CreateInstance(Type validatorType)
{
return kernel.TryGet(validatorType) as IValidator;
}
}
// I then wire both of these in a Ninject Module:
public class ValidationModule : NinjectModule
{
public override void Load()
{
this.Bind<IValidationService>().To<FluentValidationService>().InRequestScope(); // Specific to MVC.
this.Bind<IValidatorFactory>().To<NinjectValidatorFactory>().InRequestScope();
}
}
// Then I can use it inside a service:
public class FooService
{
private readonly IValidationService validationService;
public FooService(IValidationService validationService)
{
this.validationService = validationService;
}
public bool Add(Foo foo)
{
if(this.validationService.Validate(foo).Any())
{
// Handle validation errors..
}
// do other implementation details here.
}
}

Categories

Resources