I get the following error when using sharparchitecture and try to call IValidatable.IsValid on a Domain Object.
How can I register an instance of the NHibernate validator against the common service locator?
I have seen the following unit tests:
http://code.google.com/p/sharp-architecture/source/browse/trunk/src/SharpArch/SharpArch.Tests/SharpArch.Core/SafeServiceLocatorTests.cs?spec=svn385&r=385
Any help with this would really be appreciated.
The needed dependency of type IValidator could not be located with the ServiceLocator. You'll need to register it with the Common Service Locator (CSL) via your IoC's CSL adapter.
at SharpArch.Core.SafeServiceLocator`1.GetService() in C:\MyStuff\Projects\SharpArchGitHub\src\SharpArch\SharpArch.Core\SafeServiceLocator.cs:line 29
at SharpArch.Core.DomainModel.ValidatableObject.IsValid() in C:\MyStuff\Projects\SharpArchGitHub\src\SharpArch\SharpArch.Core\DomainModel\ValidatableObject .cs:line 11
at Tuhdoo.Common.Validation.ValidatableExtensions.Validate(IValidatable entity) in D:\Repository\Tuhdoo\src\Tuhdoo.Common\Validation\ValidatableExtensions.cs:line 26
This turned out to be pretty obvious I had a slap head moment when I realised I hadn't registered the IValidator with my DI Conatiner.
Related
I have following registration in my autofac container:
builder.RegisterType<EmailService>().As<IEmailService>().InstancePerLifetimeScope();
builder.RegisterType<AzureBlobStorageService>().InstancePerLifetimeScope();
Some commands depend on these services. But in my tests I don't need them, it's not what I want to test.
So I tried to rewrite registrations in following way:
builder.RegisterType<Mock<EmailService>>().As<IEmailService>().InstancePerLifetimeScope();
builder.RegisterType<Mock<AzureBlobStorageService>>().InstancePerLifetimeScope();
But I'm getting error:
Message: System.ArgumentException : The type 'Moq.Mock 1[EmailService]' is not assignable to service 'Moq.Mock`1[[IEmailService, ...]]'.
How to do it proper way?
If you want to register a mock for the IEmailService interface, you could use the RegisterInstance method:
builder.RegisterInstance(new Mock<IEmailService>().Object)
.As<IEmailService>();
I'm using StructureMap and ASP.Net Identity in my application. When I have this line in my Application_Start
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
and this is StructureMapControllerFactory:
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null && requestContext.HttpContext.Request.Url != null)
throw new InvalidOperationException(string.Format("Page not found: {0}",
requestContext.HttpContext.Request.Url.AbsoluteUri.ToString(CultureInfo.InvariantCulture)));
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}
return ObjectFactory.GetInstance(controllerType) as Controller; throws a StructureMapConfigurationException exception saying:
No default Instance is registered and cannot be automatically determined for type 'IUserStore<Person>'
but if I remove ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); line everything goes fine so it's StructureMap's problem not my code.
I think the exception is clear. It's probably about the AccountController from the Identity template, which comes with 2 constructors.
StructureMap will use the most greediest constructor by default. The template comes with 2 constructors, one default constructor and one constructor with an ApplicationUserManager object.
Without StructureMap the default constructor is called and the ApplicationUserManager will be resolved using the service locator anti pattern.
StructureMap now must create the ApplicationUserManager and because this is a concrete type it will try. If it was an abstract it will throw the exception right there. The ApplicationUserManager however has a single constructor which needs an IUserStore<Person>. Because this is an abstract and the container has no registration of this type, StructureMap is unable to create the type for you.
To solve this you should remove the default constructor and Register the ApplicationUserManager and depending services which is at least some component which, implements IUserStore.
Edit:
While the solution you mentioned in the comments may work, this is not the preferable solution because of:
Having multiple constructors is an anti-pattern
You are now using the service locator anti pattern for resolving the ApplicationUserManager from the HttpContext
The templates that come with VS2013 need some work to use with dependency injection. This will cost some time. The good news is, it is possible and doable and will greatly improve your knowledge of Owin, Asp.Net Identity, Dependency Injection and SOLID design.
There are several blogs on how to start refactoring the templates to work with dependency injection. You could read about that here and here
This is probably a bit trivial, but I must be doing something wrong. I have an MVC project, where I have two projects controlled by IoC using Windsor:
The MVC project
A project with services
Normally I would register the services using an XML file. However, I want to register all services and interfaces automatically.
All my services is placed in my services project called LetterAmazer.Business.Services, under the namespace LetterAmazer.Business.Services.Services. My interfaces, which the services derive from, is in the namespace LetterAmazer.Business.Services.Domain .
I have tried to set it up in my Global.asax, in the following way:
private void InitializeContainer()
{
var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
FilterProviders.Providers.Remove(oldProvider);
Container.Register(Component.For<IWindsorContainer>().Instance(this.Container));
Container.Install(new BootstrapInstaller());
Container.Register(
Classes.FromAssemblyInDirectory(new AssemblyFilter("LetterAmazer.Business.Services"))
.InNamespace("LetterAmazer.Business.Services.Services"));
Container.Install(new WebWindsorInstaller());
var provider = new WindsorFilterAttributeFilterProvider(this.Container);
FilterProviders.Providers.Add(provider);
DependencyResolver.SetResolver(new WindsorDependencyResolver(ServiceFactory.Container));
}
public IWindsorContainer Container
{
get { return ServiceFactory.Container; }
}
But this provides several issues. First of all, it doesn't find any services when running the Classes.FromAssemblyInDirectory call. Furthermore, this wouldn't get the interfaces.
So I am basically asking how to solve this problem in a best practice way? I have 30+ services, and I want them all, so it would make sense to add them by conventation rather than hand pick.
EDIT:
The code I ended up with:
var assembly = Assembly.LoadFrom(Server.MapPath("~/bin/LetterAmazer.Business.Services.dll")); ;
Container.Register(
Classes.FromAssembly(assembly)
.InNamespace("LetterAmazer.Business.Services.Services")
.WithServiceAllInterfaces());
I haven't used Classes.FromAssemblyInDirectory() method but I usually use FromThisAssembly() or 'FromAssemblyContaining()' methods to select assemblies. Simetimes FromAssembly("AssemblyName") is used.
I would write the following code the following way if there is no base interface for all seervices:
container.Register(
Classes.FromAssembly("LetterAmazer.Business.Services")
.InNamespace("LetterAmazer.Business.Services.Services")
.WithServiceAllInterfaces());
If there is a generic interface IService<T> I would use the following registration:
container.Register(
Classes.FromAssembly("LetterAmazer.Business.Services")
.BasedOn(typeof(IService<>))
.WithServiceAllInterfaces());
I'd like to add that all your services will be registered as Singletons if life style is not specified during registration.
You can find detailed information in the article Registering components by conventions from Castle Windsor website.
I am currently getting started with the extending of Microsoft Dynamics CRM using Plugins.
Is it possible to add Dependency injection to these plugins (for testing, loose coupling, etc. purposes)? Where can I register my IoC-container so that it's used over all the plugins of the same type?
We've been trying to unit test and apply dependency injection on our Dynamics CRM application. Unfortunately, as Microsoft support and consultants are confirmed, there is no supported way to do it. You may either transfer all of your plugin business logic to an another business class and apply dependency injection or stop thinking about it.
If you choose to fight back with Dynamics CRM, you need to define a static field on a plugin super class which will be your DI Container. As follows,
public abstract class SuperPlugin : IPlugin{
public void Execute(IServiceProvider serviceProvider){
// initialize a static container instance if not available
var containerWrapper = new ContainerWrapper{
Container = serviceProvider.GetService(typeof(IPluginExecutionContext)),
Resolver = //static resolver instance of dependency container
};
OnExecution(containerWrapper);
}
public abstract void OnExecution(IDependencyResolver resolver);
}
I really cannot understand why Microsoft doesn't simply let us register some components to the IServiceProvider implementation that they are using internally.
Ps. Since your SuperPlugin class is an IPlugin, you may forget to write the interface implementation on the sub class. But we encountered some bugs on Plugin Registration tool that is shipped with official Dynamics CRM SDK. So in case you may have the same problem you should also implement your plugins as follows,
public class MyPlugin : SuperPlugin, IPlugin{
public abstract void OnExecution(IDependencyResolver resolver){};
}
Edit: See a small example that explains the concept https://github.com/nakahparis/DIForCRM
Plugins in CRM are the Bane of Unit Testing:
Issues with non-plugin test
No way to temporarily disable
Easy to forget it is running
Issues with testing plugins themselves
Unable to unit test and attach to process
A lot to mock out, Pipeline, Service Provider etc
Runs multi-threaded
This has led me to the following solution for testing plugins:
Get rid of the plugin context as quickly as possible, extracting out all objects and service required from it right away.
Create an ExecutePlugin method to hook unit tests into, and immediately call this method after extracting the objects from the plugin context.
Push as much code as possible into the business layer.
This results in plugins that look like this (with a heavy use of extension methods to make this simpler):
public void Execute(IServiceProvider provider)
{
var context = provider.GetContext();
var service = provider.GetService(context);
var target = GetTarget<Contact>(context);
if (target == null || !target.ContainsAllNonNull(c => new
{
c.FirstName,
c.LastName,
}))
{
// Entity is of the wrong type, or doesn't contain all of the required attributes
return;
}
ExecutePlugin(service, target);
}
public void ExecutePlugin(IOrganizationService service, Contact target){
// Logic Goes Here
}
Once this is done, the only thing you need to unit test the ExceutePlugin is your own IOrganizationService that mocks out the required calls and you have your unit testing done. I don't even bother unit testing the Execute method. Either it'll work, or it won't and blow chow on the first use from within CRM.
I'm getting an error:
StructureMap Exception Code: 202
No Default Instance defined for PluginFamily MVCPoco.Services.IService, MVCPoco.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Line 96: {
Line 97: Type controllerType = base.GetControllerType(context, controllerName);
Line 98: return ObjectFactory.GetInstance(controllerType) as IController;
Line 99: }
Line 100: }
the error occurs in line 98
Any ideas?
I'm using asp.net mvc 2 preview 2 that ships with visual studio 2010.
The controller you are trying to instantiate has a constructor dependency on IService. You have to make sure that you register a concrete implementation of IService when you configure StructureMap.
The DefaultConventionScanner will only register implementations that have the same name as their interface (without the leading I). So, unless your implementation of IService is named Service, it will not be registered automatically. To register it explicitly, add something like this to your inititalization script:
x.For<IService>().Use<MyService>();
Alternatively, if you are running StructureMap from the latest source code, you can make use of the SingleImplementationScanner in your Scan() expression:
y.With(new SingleImplementationScanner());
and that will automatically register concrete types if they are the only implementation of an interface in the scanned code, regardless of name.
You must register the types to be injected at application start within the ObjectFactory.Configure function. Check out the documents over on Structure Map's site for Configuring your IOC Container.
Andrew
Well, i've set up correctly the structuremap i've just switched to the method
public static void Configure()
{
ObjectFactory.Initialize(x =>
x.AddRegistry(new IOCRegistry())); // in here i have registered my dependencies with for method.
}