In a class I am using this code:
public User CurrentUser
{
get
{
var unityContainer = new UnityContainer();
var httpContextHelper = unityContainer.Resolve<HttpContextHelper>();
return httpContextHelper.GetUser();
}
}
This is in the Bootstrapper.cs file:
public static class Bootstrapper
{
public static void Initialise()
{
IUnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType<IHttpContextHelper, HttpContextHelper>();
DependencyResolver.SetResolver(new UnityDependencyResolver(unityContainer));
}
}
I cannot use constructor injection here because it is a base class and it would take quite some work to refactor.
But how would I unit test this? I cannot find a suitable method to mock unityContainer.Resolve.
First things first the following code is wrong:
get
{
var unityContainer = new UnityContainer();
var httpContextHelper = unityContainer.Resolve<HttpContextHelper>();
return httpContextHelper.GetUser();
}
You are creating a new Unity container which of course is empty and then you are attempting to resolve some instances from this container which would simply call the default constructor of the HttpContextHelper class. Gosh I hate Unity for not throwing an exception when you attempt to resolve an instance of something that has never been registered into the container (which is what you are doing here). Instead it is silently calling its constructor with most known (registered) dependencies.
So this will not return the instance you have registered in your Bootstrapper because there you have a different instance of the UnityContainer in which you have registered the IHttpContextHelper instance.
So the first step towards refactoring this is to use the DependencyResolver:
public User CurrentUser
{
get
{
var httpContextHelper = DependencyResolver
.Current
.GetService<IHttpContextHelper>();
return httpContextHelper.GetUser();
}
}
Now in your unit test you could write a custom dependency resolver:
public class DepepndecyResolverMock : IDependencyResolver
{
private readonly IDictionary<Type, object> kernel;
public DepepndecyResolverMock(IDictionary<Type, object> kernel)
{
this.kernel = kernel;
}
public object GetService(Type serviceType)
{
return this.kernel[serviceType];
}
public IEnumerable<object> GetServices(Type serviceType)
{
throw new NotImplementedException();
}
}
which you could configure for your tests:
var kernel = new Dictionary<Type, object>
{
{ typeof(IHttpContextHelper), new HttpContextHelperMock() }
};
DependencyResolver.SetResolver(new DepepndecyResolverMock(kernel));
This being said, this code is still horribly wrong. It might allow you to unit test it but please I insist, this is wrong design. Do not use it. This uses the service locator pattern which is an anti-pattern.
The proper way to do this is to invert the control of this class so that it doesn't need to fetch its dependencies, but its dependencies need to be injected into it. So instead of wasting your time in useless patterns, refactor your code so that it uses real dependency injection.
Related
I'm trying to use an IoC container inside the WebApi template. I've created an empty Web App Framework project, and selected to use WebApi. I've then added the Unity NuGet package and added the following to Application_Start:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
UnityConfig.Register();
}
The UnityConfig:
public class UnityConfig
{
public static UnityContainer Register()
{
var container = new UnityContainer();
container.RegisterType<IMyClass, MyClass>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityResolver(container);
return container;
}
}
My UnityResolver is here (the code is largely plagiarised, but it seems pretty bog standard):
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
container.Dispose();
}
}
When I now run this, I get the following error:
Unity.Exceptions.ResolutionFailedException: 'Resolution of the
dependency failed, type =
'System.Web.Http.Hosting.IHostBufferPolicySelector', name = '(none)'.
Exception occurred while: while resolving. Exception is:
InvalidOperationException - The current type,
System.Web.Http.Hosting.IHostBufferPolicySelector, is an interface and
cannot be constructed. Are you missing a type mapping?
----------------------------------------------- At the time of the exception, the container was: Resolving
System.Web.Http.Hosting.IHostBufferPolicySelector,(none) '
Clearly, after telling it which IoC library I want to use, I need to inject some internal dependencies, or tell it to, or perhaps, register this earlier (or later).
Clearly, after telling it which IoC library I want to use, I need to inject some internal dependencies, or tell it to, or perhaps, register this earlier (or later).
That's true. You need to register all of the types that will be resolved through Unity. The error message indicates you are missing IHostBufferPolicySelector, so you need to register it.
public static UnityContainer Register()
{
var container = new UnityContainer();
// Register all types with Unity here
container.RegisterType<IHostBufferPolicySelector, OwinBufferPolicySelector>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityResolver(container);
return container;
}
I don't know for sure if OwinBufferPolicySelector is the one you need because you haven't provided enough info, but you do need to map an implementation for it (and probably several other interfaces) in order to proceed.
As noted in the comments, it would probably be easier if you install one of the premade Unity packages (such as Unity.WebAPI) to supply this implementation.
It will also help considerably if you follow the Dependency Injection in ASP.NET Web API 2 documentation.
I am trying to implement Unity as an IoC container in a learning project I am working on. I have a layered application, UI->Service->Logic->DataAccess.
It's an MVC Application on the UI side.
In my controller, I have a constructor:
public HomeController()
{
_container = new UnityContainer();
_container.RegisterType<IUserService, UserService>();
_container.RegisterType<IUserLogic, UserLogic>();
}
I then attempt to use the IService in one of my methods:
var service = _container.Resolve<IUserService>();
ReplyDto reply = service.Login(model.Email, model.Password);
But then get this error:
Resolution of the dependency failed, type = "Services.IUserService",
name = "(none)".
I'm not sure why it's saying this. Do I maybe have an issue with MVC and the constructor? Breakpoint on the Resolve line shows that the _container does have the interface I am trying to resolve.
My UserService class has this in the constructor:
private IUserLogic _userlogic;
public UserService(IUserLogic logic)
{
_userlogic = logic;
}
The Logic layer class is defined like this:
public class UserLogic : IUserLogic
{
public ILog _logger;
public IData _data;
public UserLogic(IData data, ILog logger)
{
_data = data;
_logger = logger;
}
I am still in the process of propagating the IoC patter down through all layers.
And finally, the data access layer is defined as:
public class Data :IData
{
Log _logger = new Log();
MyEntities entities;
public Data()
{
entities = new MyEntities();
var instance = System.Data.Entity.SqlServer.SqlProviderServices.Instance;
}
My _container has reference to the IUserLogic interfaces and which concrete class to use.
UserLogic(IData data, ILog logger) - neither IData nor ILog shown as registered in container - so if code is exactly like you have in the post it is the reason why IUserLogic can't be resolved when unity tries to pass argument to UserService(IUserLogic) constructor.
Fix: register all dependencies (recursively)
To achieve that consider:
make sure types with no dependencies has constructors without arguments
register instances instead of types - if that works for your system
make constructors depend on concrete types (as all concrete types by default registered with Unity) - not testable choice...
provide parameters for all non-interface/non class arguments like int/string (How resolve a dependency with unity passing arguments in the constructor?)
You should register container in the Global.asax.cs
public class Global : HttpApplication
{
private void Application_Start(object sender, EventArgs e)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IUserService, UserService>();
container.RegisterType<IUserLogic, UserLogic>();
UnityDependencyResolver dependencyResolver = new UnityDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver;
DependencyResolver.SetResolver(dependencyResolver);
}
}
Hi am working on console application which uses Dependency Injection pattern, i have created the interface like
public interface IRecurringTransactionPlanDataService : IService<RecurringTransactionPlan>
{
IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData();
}
and the class implements as
public class RecurringTransactionPlanDataService : Service<RecurringTransactionPlan>, IRecurringTransactionPlanDataService
{
private readonly IRepositoryAsync<RecurringTransactionPlan> _repository;
public RecurringTransactionPlanDataService(IRepositoryAsync<RecurringTransactionPlan> repository)
: base(repository)
{
_repository = repository;
}
public IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData()
{
return _repository.RecurringTransactionPlanData();
}
}
The repository:
public static class RecurringTransactionPlanRepository
{
public static IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData(this IRepository<RecurringTransactionPlan> repository)
{
return repository.Queryable();
}
}
the above code all in separate projects, i am using this in MVC and also in console application, while using in MVC there is no error fetching data from db by UnityConfig.cs, but in console application we need to manually register and resolve the interfaces, i have tried this,
My Console Application:
public class RecurringTransaction
{
public readonly IRecurringTransactionPlanDataService _recurringTransactionPlanDataService;
public RecurringTransaction()
{
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
}
}
public class Program
{
public static void Main(string[] args)
{
FeePaymentTracker.UnityConfig.RegisterComponents();
RecurringTransaction rt = new RecurringTransaction();
var restult = rt.GetRecurringTransactionRecords();
}
}
am getting the above error. expecting your ideas to resolve the error.
In your RecurringTransaction-method you create a new container and then you register RecurringTransactionPlanDataService in that new container. But you do not register the dependencies that the implementation RecurringTransactionPlanDataService has. That container will only have one registration.
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
Since RecurringTransactionPlanDataService has a dependency to IRepositoryAsync<RecurringTransactionPlan> you need to register that as well.
Change your code to:
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
container.RegisterType<IRepositoryAsync<RecurringTransactionPlan>, YourRepositoryImplementation>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
As a sidenote you may want to re-use the same container. In console-applications I usually resolve a "ProgramStarter", which then gets the correct injections. This way you only need to use the service locator anti-pattern in the root. But can use proper DI in the rest of the application.
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ProgramStarter, ProgramStarter>();
// Pass the same container to the config.
FeePaymentTracker.UnityConfig.RegisterComponents(container);
var program = container.Resolve<ProgramStarter>();
program.Run();
}
}
public class ProgramStarter
{
IRecurringTransactionPlanDataService _dataService;
public ProgramStarter(IRecurringTransactionPlanDataService dataService)
{
_dataService = dataService;
}
public void Run()
{
// Do stuff.
}
}
in the code that you have posted you have an interface called IPaymentService and its implementation. It seems ok. But then in the screenshot you are trying to resolve a dependency called RecurringTransactionPlanDataService. Make your that you have registered this dependency. Could you add information about how you are registering the dependencies in the container?
The problem in your code is that you are trying to resolve the implementation instead of the interface. You should change the following line:
_recurringTransactionPlanDataService = container.Resolve<RecurringTransactionPlanDataService>();
with that:
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
Cheers,
I'm getting null reference exception when trying to access a singleton class from my ASP.NET MVC Controller Action. I use Autofac as the IoC Container.
Here is the code:
Register dependencies method:
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
const string nameOrConnectionString = "name=DefaultConnection";
builder.RegisterApiControllers(typeof(WebApiConfig).Assembly);
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterGeneric(typeof(EntityRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Service<>)).As(typeof(IService<>)).InstancePerLifetimeScope();
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerLifetimeScope();
builder.Register<IEntitiesContext>(b =>
{
var logger = b.Resolve<ILogger>();
var context = new InterfaceContext(nameOrConnectionString, logger);
return context;
}).InstancePerRequest();
builder.Register(b => NLogLogger.Instance).SingleInstance();
builder.Register(b => UserControlHelper.Instance).SingleInstance();
builder.RegisterModule(new IdentityModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver =
new AutofacWebApiDependencyResolver(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
UserControlHelper class:
public class UserControlHelper
{
private static volatile UserControlHelper _instance;
private static readonly object SyncRoot = new object();
private static IService<Administrator> _service;
private static IService<Customer> _customerService;
private UserControlHelper() { }
private UserControlHelper(IService<Administrator> service, IService<Customer> customerService)
{
_service = service;
_customerService = customerService;
}
public static UserControlHelper Instance
{
get
{
if (_instance == null)
{
lock (SyncRoot)
{
if (_instance == null)
_instance = new UserControlHelper(_service, _customerService);
}
}
return _instance;
}
}
public static string GetUserData(int userId, string type)
{
var getImage = _service.GetByIdAsync(userId);
switch (type)
{
case "Image":
{
return getImage.GetAwaiter().GetResult().Image;
}
case "Name":
{
return getImage.GetAwaiter().GetResult().FullName;
}
case "Email":
{
return getImage.GetAwaiter().GetResult().Email;
}
case "AllUsers":
{
return _customerService.GetCountAsync(userId).GetAwaiter().GetResult().ToString();
}
default:
return "No Data";
}
}
}
I'm calling it like this:
ViewBag.FullName = UserControlHelper.GetUserData(UserId, "Name");
Your _service variable is going to be null all the time. Hence you maybe getting the null referece.
private static IService<Administrator> _service;
This variable is never instantiated (manually or via Autofac)
And when you call your method, this is the code that might be causing the null reference.
var getImage = _service.GetByIdAsync(userId);
because _service is null
For all the Autofac wireup being done, there is no place we are indicating to Autofac that this class needs to be instantiated automatically. The class doesn't seem to be a controller (MVC or API) or any dependencies to the controller.
Also, the _service variable being static doesn't help with Autofac.
To solve the problem, you might want to rethink this class in terms of a controller or better, a dependency (constructor parameter) to a controller, with the _service and such variables as instance variables rather than static variables, where Autofac cannot help you much.
This way, when the controller is instantiated by Autofac, it'll automatically create an instance of 'UserControlHelper' for you.
Answering to your comment (You need a singleton of UserControlHelper):
you can leverage Autofac for this.
we'll make this class a constructor parameter of your controller.
And let Autofac know to instantiate this as a singleton.
public class MyController: Controller
{
public MyController(UserControlHelper helper)
{
ViewBag.FullName = helper.GetUserData(UserId, "Name");
}
}
And when you register this class with Autofac, you can do:
build.RegisterType<UserControlHelper>().SingleInstance();
This would mean that you have to remove the Instance variable and any singleton-like logic in your class. And also convert the static methods to instance methods. And convert the constructor to a public one.
It is best to let Autofac/frameworks do the grunt work of Singletons/other such functionality. (Lazy variables are another such tool)
And we can focus on keeping your class relevant to the business logic.
And if you really want to do the singleton implementation yourself, you can still register it with autofac as:
builder.RegisterInstance<UserControlHelper>(singletonInstanceYouConstructed);
But in general, I have found it to be simpler to let Autofac manage the whole lifetime management.
In my bootstrapper:
namespace Conduit.Mam.ClientServices.Common.Initizliaer
{
public static class Initializer
{
private static bool isInitialize;
private static readonly object LockObj = new object();
private static IUnityContainer defaultContainer = new UnityContainer();
static Initializer()
{
Initialize();
}
public static void Initialize()
{
if (isInitialize)
return;
lock (LockObj)
{
IUnityContainer container = defaultContainer;
//registering Unity for MVC
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
//registering Unity for web API
// GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
#region managers
container.RegisterType<ISettingsManager, SettingsManager>();
container.RegisterType<IMamDataManager, MamDataManager>();
container.RegisterType<IAppsDataManager, AppsDataManager>();
#endregion
if (!isInitialize)
{
isInitialize = true;
}
}
}
}
}
in my controller's code:
ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();
hovering on mUnityContainer I see ISettingsManager is mapped to SettingsManager
but then I get the error:
Exception is: InvalidOperationException - The current type, is an
interface and cannot be constructed. Are you missing a type mapping?
I have also tried
ISettingsManager sm = (ISettingsManager)mUnityContainer.Resolve<>(typeof(ISettingsManager));
but no use
Just for others (like me) who might have faced the above error. The solution in simple terms.
You might have missed to register your Interface and class (which implements that inteface) registration in your code.
e.g if the error is
"The current type, xyznamespace. Imyinterfacename, is an interface and cannot be constructed. Are you missing a type mapping?"
Then you must register the class which implements the Imyinterfacename in the UnityConfig class in the Register method. using code like below
container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();
You are incorrectly using Dependency Injection. The proper way is to have your controllers take the dependencies they need and leave to the dependency injection framework inject the concrete instances:
public class HomeController: Controller
{
private readonly ISettingsManager settingsManager;
public HomeController(ISettingsManager settingsManager)
{
this.settingsManager = settingsManager;
}
public ActionResult Index()
{
// you could use the this.settingsManager here
}
}
As you can see in this example the controller doesn't know anything about the container. And that's how it should be.
All the DI wiring should happen in your Bootstraper. You should never use container.Resolve<> calls in your code.
As far as your error is concerned, probably the mUnityContainer you are using inside your controller is not the same instance as the one constructed in your Bootstraper. But since you shouldn't be using any container code in your controllers, this shouldn't be a problem anymore.
In my case, I was getting this error despite registering an existing instance for the interface in question.
Turned out, it was because I was using Unity in WebForms by way of the Unity.WebForms Nuget package, and I had specified a Hierarchical Lifetime manager for the dependency I was providing an instance for, yet a Transient lifetime manager for a subsequent type that depended on the previous type - not usually an issue - but with Unity.WebForms, the lifetime managers work a little differently... your injected types seem to require a Hierarchical lifetime manager, but a new container is still created for every web request (because of the architecture of web forms I guess) as explained excellently in this post.
Anyway, I resolved it by simply not specifying a lifetime manager for the types/instances when registering them.
i.e.
container.RegisterInstance<IMapper>(MappingConfig.GetMapper(), new HierarchicalLifetimeManager());
container.RegisterType<IUserContext, UserContext>(new TransientLifetimeManager());
becomes
container.RegisterInstance<IMapper>(MappingConfig.GetMapper());
container.RegisterType<IUserContext, UserContext>();
So that IMapper can be resolved successfully here:
public class UserContext : BaseContext, IUserContext
{
public UserContext(IMapper _mapper) : base(_mapper)
{
}
...
}
In my case, I have used 2 different context with Unitofwork and Ioc container so i see this problem insistanting while service layer try to make inject second repository to DI. The reason is that exist module has containing other module instance and container supposed to gettng a call from not constractured new repository.. i write here for whome in my shooes
May be You are not registering the Controllers.
Try below code:
Step 1.
Write your own controller factory class
ControllerFactory :DefaultControllerFactory by implementing defaultcontrollerfactory
in models folder
public class ControllerFactory :DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
try
{
if (controllerType == null)
throw new ArgumentNullException("controllerType");
if (!typeof(IController).IsAssignableFrom(controllerType))
throw new ArgumentException(string.Format(
"Type requested is not a controller: {0}",
controllerType.Name),
"controllerType");
return MvcUnityContainer.Container.Resolve(controllerType) as IController;
}
catch
{
return null;
}
}
public static class MvcUnityContainer
{
public static UnityContainer Container { get; set; }
}
}
Step 2:Regigster it in BootStrap:
inBuildUnityContainer method
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
//RegisterTypes(container);
container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>();
MvcUnityContainer.Container = container;
return container;
}
Step 3:
In Global Asax.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Bootstrapper.Initialise();
ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
}
And you are done
I had this problem, and the cause was that I had not added the Microsoft.Owin.Host.SystemWeb NuGet package to my project. Although the code in my startup class was correct, it was not being executed.
So if you're trying to solve this problem, put a breakpoint in the code where you do the Unity registrations. If you don't hit it, your dependency injection isn't going to work.
Below code will be helpful for you
public static IUnityContainer Initialise(IUnityContainer container = null)
{
if (container == null)
{
container = new UnityContainer();
}
container.RegisterType<ISettingsManager, SettingsManager>();
container.Resolve<SettingsManager>();
container.RegisterType<SettingsManagerController>(new InjectionProperty("_SettingManagerProvider", new ResolvedParameter<ISettingManager>()));
return container;
}