I use SimpleInjector in mvc with this code
public static class SimpleInjectorInitializer
{
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
container.Register<IPersonRepository, PersonEntityRepository>();
}
}
but now I want to test LightInject Ioc in my mvc application but How ?
I wrote this code
[assembly: WebActivator.PostApplicationStartMethod(typeof(LightInjectInitializer), "InitializeLI")]
public static class LightInjectInitializer
{
public static void InitializeLI()
{
var container = new ServiceContainer();
InitializeContainer(container);
container.RegisterControllers(Assembly.GetExecutingAssembly());
container.EnableMvc();
}
private static void InitializeContainer(ServiceContainer container)
{
container.Register(typeof(PersonEntityRepository), typeof(IPersonRepository), new PerScopeLifetime());
}
}
but show me this error
No parameterless constructor defined for this object.
Can anyone help me for writing equivalent code that working in MVC ?
Sample Code : Download
I am the author of LightInject and would like to help you out.
This static initialize method? Where is it called from.
The reason that you get this error is probably because the initialize code did not execute.
If you would like further assistance, it would be valuable to see what you have in global.asax.cs.
This page also contains information about how to set this up.
http://www.lightinject.net/#mvc
Please change the controller registration line to:
container.RegisterControllers(typeof(MVCApplicationNamespace.Controllers.HomeController).Assembly);
Related
I will try to show my problem with a sample code easier to understand.
I have used WebApplicationFactory to develop my acceptance tests. Let's say that I have the typical minimal Program.cs with the following line to register one of my modules:
builder.Services.RegisterModule<StartupRegistrationModule>(builder.Configuration, builder.Environment);
And this module is declared like this:
internal sealed class StartupRegistrationModule : IServiceRegistrationModule
{
public static Dictionary<string, string> _dictionary = new();
public void Register(IServiceCollection services, IConfiguration configuration, IHostEnvironment hostEnvironment)
{
// Lot of modules being registered
_dictionary.Add("key", "value");
}
}
One of my tests file is like this:
public sealed class MyTests : AcceptanceTestBase
{
[Fact]
public void Test1()
{
// arrange
// act
// assert
}
[Fact]
public void Test2()
{
// arrange
// act
// assert
}
[Fact]
public void Test3()
{
// arrange
// act
// assert
}
}
And AcceptanceTestBase is:
public abstract class AcceptanceTestBase : IDisposable
{
protected HttpClient _httpClient;
protected WebApplicationFactory<Program> _webApplicationFactory;
public AcceptanceTestBase()
{
_webApplicationFactory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
// ... Configure test services
});
_httpClient = _webApplicationFactory.CreateClient();
}
public void Dispose()
{
_httpClient.Dispose();
_webApplicationFactory.Dispose();
}
}
If I try to execute all these tests my tests will fail in the second test run because the WebApplicationFactory is trying to build again the Application but it already has the key in the dictionary and it will fail. See the image for more understanding on the problem.
So my question is, how can I build the application in different scopes to do not share this dictionary state?
Thanks :)
Update:
The real static dictionary is saved behind this nuget package that keeps the track of all my circuit breaker policies state. I do not actually need even the HttpClients for my tests but did not find a way to remove them and not load this. I tried removing all the HttpClients to see if it also removes their dependencies, but it does not seem to make the trick.
It is because you are using:
internal sealed class StartupRegistrationModule : IServiceRegistrationModule
{
/// .. static here
public static Dictionary<string, string> _dictionary = new();
public void Register(IServiceCollection services, IConfiguration configuration, IHostEnvironment hostEnvironment)
{
// Lot of modules being registered
_dictionary.Add("key", "value");
}
}
The static Dictionary is shared over all your tests because they run in the same process.
Each test starts a new (Test-)WebHost but the dictionary remains untouched.
My proposal is to not use statics anywhere in DI context to prevent such hidden traps.
I don't know the purpose of your Dictionary here but maybe you can extract this to a singleton registration which you can replace in your (Test.)WebHost on each new test / startup?
Current Code
public class SystemUserController : ApiController
{
ISystemUserDataAccess dataAccess;
public SystemUserController(ISystemUserDataAccess userDataAccess)
{
dataAccess = userDataAccess;
}
//Other api methods
}
And ISystemUserDataAccess is the interface which contains all the data access methods. I have following installer code, which is being called by the Global.asax
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For(typeof(IConnectDB)).ImplementedBy(typeof(ConnectDB)),
Component.For(typeof(ISystemUserDataAccess)).ImplementedBy(typeof(SystemUserDataAccess));
}
}
public class ApiControllersInstaller : IWindsorInstaller
{
public void Install(Castle.Windsor.IWindsorContainer container,
Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<ApiController>()
.LifestylePerWebRequest());
}
}
Container Initialization at Global.asax
container = new WindsorContainer();
container.Install(FromAssembly.This());
It is all working fine. userDataAccess get injected properly and i can call all the DataAccess method without any problem.
My Data Access class looks like below.
public class SystemUserDataAccess : ISystemUserDataAccess
{
IConnectDB connectionManager;
public SystemUserDataAccess(IConnectDB connection)
{
connectionManager = connection;
}
//Data access methods
}
Actual Problem
Now I need an instance of SystemUserDataAccess within a non ApiController class (this is a static class). When I tried below code, but it is giving an exception, saying it couldnt find any component registered.
IWindsorContainer container = new WindsorContainer();
var asas = container.Resolve<ISystemUserDataAccess>();
When I inspect the container object, "All component" property is 0. Which is why it is throwing the error. What am I doing wrong here? Do i need another installer for that non ApiController class?
Instead of doing container.Install(FromAssembly.This()); in global.asax, use container.install(new RepositoriesInstaller());
I have a MVC application and inject my repositories to my controller what works properly.
Additionally I have a Webservice in my solution which uses exactly the same repositories but when my Webservice is called my repository properties are null.
I register my repositories the following way:
container.Register(Classes.FromAssembly(Assembly.GetAssembly(typeof(HdtRepository))).InSameNamespaceAs<HdtRepository>().WithService.DefaultInterfaces().LifestyleTransient());
my repository properties look like:
public IUserRepository _userRepo { get; set; }
public IHdtRepository _hdtRepo { get; set; }
public ITimeRecordRepository _timeRepo { get; set; }
Can someone tell me why the repositories are not injected to my webservice?
For now I added the following to the constructor of my webservice:
public MyWebservice()
{
_userRepo = MvcApplication.container.Resolve<IUserRepository>();
_hdtRepo = MvcApplication.container.Resolve<IHdtRepository>();
_timeRepo = MvcApplication.container.Resolve<ITimeRecordRepository>();
_locationRepo = MvcApplication.container.Resolve<ILocationRepository>();
_wayRepo = MvcApplication.container.Resolve<IWayPointRepository>();
_wayDataRepo = MvcApplication.container.Resolve<IWayDataRepository>();
}
but as far as I know this is actually a antipattern.
I'm new to all that IoC stuff so could someone please tell me where the problem is.
Cheers,
Stefan
First lets get your project setup with some Windsor installers. They look like this for the most part.
public class ServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IEncryptionService().ImplementedBy<EncryptionService>());
}
}
in your App_Start folder add a class called ContainerConfig.cs that could look something like this.
public class ContainerConfig
{
private static IWindsorContainer _container;
public static IWindsorContainer ConfigureContainer()
{
_container = new WindsorContainer();
_container.Install(FromAssembly.This()).Install(FromAssembly.Named("Project.Dependency"));
_container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true));
_container.AddFacility<TypedFactoryFacility>();
var controllerFactory = new WindsorControllerFactory(_container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
return _container;
}
}
Please note that I have a separate project for my Dependency Injection hence the _container.Install(FromAssembly.This()).Install(FromAssembly.Named("Project.Dependency")); line... You can remove the latter .Install(FromAssembly) part.
In your Global.asax you can do something like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ContainerConfig.ConfigureContainer();
}
Now in your controllers you can do this:
public class TempController : Controller
{
private readonly IEncryptionService _encryptionService;
public TempController(IEncryptionService encryptionService )
{
_encryptionService = encryptionService;
}
public ActionResult Index()
{
// Example of calling a method on the encryption service.
string hash, salt;
_encryptionService.GethashAndSaltString("I Need Some Loving", out hash, out salt);
return View();
}
}
Please let me know if you get something working with constructor injection. Solving that issue will be a great help going forward and you won't be using property injection. Once we get all of that sorted out we can look at your webervice issues.
I guess this is not possible as far as I've read some other posts.
The problem is that you can't create a custom factory for a Webservice like "WindsorControllerFactory" for the controller.
I'm going to switch to WCF Service.
Resolve a System.Web.Services.WebService instance with Castle (for AOP purposes)
I am trying to use ServiceStack with Ninject rather than Funq. I have the following:
public interface IContainerAdapter
{
T Resolve<T>();
T TryResolve<T>();
}
public class NinjectIocAdapter : IContainerAdapter
{
private readonly IKernel kernel;
public NinjectIocAdapter(IKernel kernel)
{
this.kernel = kernel;
}
public T Resolve<T>()
{
return this.kernel.Get<T>();
}
public T TryResolve<T>()
{
return this.kernel.TryGet<T>();
}
}
Then inside my Configure method:
public override void Configure(Funq.Container container)
{
//Set JSON web services to return idiomatic JSON camelCase properties
ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
IKernel kernel = new StandardKernel();
container.Adapter = new NinjectIocAdapter(kernel);
//Set MVC to use the same Funq IOC as ServiceStack
//ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
}
But I get the following error:
Cannot implicitly convert type 'NinjectIocAdapter' to 'ServiceStack.Configuration.IContainerAdapter'.
I'm also unsure whether I have to uncomment the line to set MVC to use Funq IoC? I have commented it out as I will be using Ninject. Is that correct?
I assume once this is all working. I can simply register any dependencies inside:
private static void RegisterServices(IKernel kernel)
{
}
The code exactly matches the documentation with one subtle difference.
You have to use ServiceStack.Configuration.IContainerAdapter instead of your own IContainerAdapter
.
Delete your implementation, add a reference to ServiceStack.Configuration and you should be fine.
Here is the set up that is not working
Using Ninject V3.0
public class LoggerModule : NinjectModule{
public override void Load()
{
Bind<ILogger>.ToProvider(MyLoggerProvider);
}
}
public class MyLoggerProvider: IProvider<ILogger>
{
public object Create(IContext context){
return new OneOfMyLoggers();
}
}
In my application wherever I inject instance of ILogger (using constructor or property injection, just does matter) I never get instance of ILogger resolved.
But If do not use module and/or povider, and bind when kernel is created, everything works like a charm. The following works
public class MyDiResolver()
{
public MyDiResolver()
{
MyKernel = new StandardKernel();
MyKernel.Bind<ILogger>().To<OneOfMyLoggers>();
}
}
The same arrangement of modules and providers works fine in Ninject2.x version. Is there something different about Ninject V3.0 that I am missing?
Thanks
Try passing the module into the StandardKernel so it knows to use it:
using (IKernel kernel = new StandardKernel(new LoggerModule()))
{
ILogger logger = kernel.Get<OneOfMyLoggers>();
}