I would like to implement CastleWindsor with the MVP pattern, but I keep getting an 'Object Reference Not Set to an Object reference on the Presenter when the repository is called to obtain some data.
This is how I did it and I am wondering if there is anything wrong, so please let me know if you can:
Presenter:
public class CategoryPresenter
{
ICategoryRepository categoryRepository;
ICategoryView categoryView;
public CategoryPresenter(ICategoryView _categoryView, ICategoryRepository _categoryRepository)
{
categoryView = _categoryView;
categoryRepository = _categoryRepository;
}
//public CategoryPresenter(ICategoryView _categoryView) : this (_categoryView, new CategoryRepository())
//{ }
public CategoryPresenter(ICategoryView _view)
{
categoryView = _view;
}
public IEnumerable<object> GetActiveCategories()
{
return categoryRepository.GetActiveCategories();
}
}
IoC Class:
public static class IoC
{
public static IWindsorContainer windsorContainter { get; set; }
}
IoCConfig Class:
class IoCConfig
{
public static IWindsorContainer RegisterCastleWindsorContainer()
{
IWindsorContainer windsorContainer = new WindsorContainer()
.Install(new RepositoryInstaller())
IoC.windsorContainter = windsorContainer;
return windsorContainer;
}
}
Installer Class:
public class RepositoryInstaller: IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<ICategoryRepository>().ImplementedBy<CategoryRepository>).LifestyleTransient());
}
}
Finally in Global.ascx file I am doing this at App_Start:
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
IoCConfig.RegisterCastleWindsorContainer();
}
With this, the error message is as said above; the error happens at the presenter's method: GetActiveCategories();
As you see at no where in code I invoke the resolve method on the container.
Please let me know if if you have any suggestions.
Thank you.
I have resolved this to the IoC Class
public static T Resolve<T>()
{
try
{
return windsorContainer.Resolve<T>();
}
catch (Exception e)
{
throw e;
}
}
And then add this to the presenter:
ICategoryRepository categoryRepository = IoC.Resolve<ICategoryRepository>();
ICategoryView categoryView = IoC.Resolve<ICategoryView>();
Related
I am working on a Xamarin.Android project developed by another developer. I got to know that they have used Dependancy Injection. There is a class like this
public class RemoteSupportHandler : DataAccessor<FwDataContext>, IRemoteSupportSettingHandler
{
private RemoteSupportSetting[] _cached;
public RemoteSupportHandler(IDatabaseController db, ILogger logger, IPerfLogger perfLogger)
: base(db, logger, perfLogger)
{
}
public async Task<RemoteSupportSetting> GetRemoteSupportDemoVideoUrlAsync()
{
return await WithDataContextAsync(ctx =>
{
return (from row in ctx.RemoteSupportSettings
where row.ParamName == "DEMO_VIDEO"
select new RemoteSupportSetting
{
ParamName = row.ParamName
}).FirstOrDefault();
});
}
}
In another file, they have registered this class with UnityContainer. Now I want to call this GetRemoteSupportDemoVideoUrlAsync() method from my Activity. I know I cannot create an object using this constructor. I have no idea how I should I do this.
Registration Code
public class Registrar : IRegistrar {
protected virtual void OnApplyInitializedRegistrations(IUnityContainer container) {
container.RegisterType<IRemoteSupportSettingHandler, RemoteSupportHandler>(new ContainerControlledLifetimeManager());
}
}
public interface IRegistrar
{
void ApplySessionRegistrations(IUnityContainer container);
void ApplyInitializedRegistrations(IUnityContainer container);
}
UPDATE 2
public abstract class MyApplication : Application, IPlatformApplication {
public IUnityContainer AppUnityContainer => _container;
protected virtual void OnLaunched()
{
IActivityService activityService = new ActivityService(this);
AppUnityContainer.RegisterInstance(activityService);
AppUnityContainer.RegisterType<IRegistrar, PlatformRegistrar>();
}
}
I have NotificationJob class where I have all the functions related to Notification Feature for my .Net Core application. It has some injected dependencies from Domain services. I am having a problem trying to inject INotificationJob interface of the class into the CoreModule of the project.
I initially tried injecting the interface directly into the CoreModule but failed so I created another module in the same file called NotificationModule where I inject INotificationJob interface. Then I try to link it with the CoreModule using [DependsOn(typeof(oasisCoreModule))] annotation.
Core Module of the project
[DependsOn(
typeof(AbpZeroCoreModule),
typeof(AbpHangfireAspNetCoreModule),
typeof(AbpWebCommonModule)
)]
public class oasisCoreModule : AbpModule
{
public override void PreInitialize()
{
Configuration.Modules.AbpWebCommon().SendAllExceptionsToClients = true;
Configuration.BackgroundJobs.UseHangfire();
Configuration.Auditing.IsEnabledForAnonymousUsers = true;
// Declare entity types
Configuration.Modules.Zero().EntityTypes.Tenant = typeof(Tenant);
Configuration.Modules.Zero().EntityTypes.Role = typeof(Role);
Configuration.Modules.Zero().EntityTypes.User = typeof(User);
oasisLocalizationConfigurer.Configure(Configuration.Localization);
// Enable this line to create a multi-tenant application.
Configuration.MultiTenancy.IsEnabled = oasisConsts.MultiTenancyEnabled;
// Configure roles
AppRoleConfig.Configure(Configuration.Modules.Zero().RoleManagement);
Configuration.Settings.Providers.Add<AppSettingProvider>();
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(oasisCoreModule).GetAssembly());
}
public override void PostInitialize()
{
IocManager.Resolve<AppTimes>().StartupTime = Clock.Now;
}
}
// This is the custom module that I created in the same file as the core module.
[DependsOn(typeof(oasisCoreModule))]
public class NotificationModule : AbpModule
{
INotificationJob _job;
public NotificationModule(INotificationJob job)
{
_job = job;
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
public override void PostInitialize()
{
_job.Loop();
}
}
INotificationJob Interface I am Injecting into the NotificationModule
public interface INotificationJob: IDomainService
{
void Loop();
void CheckTickets();
void CheckReminders(string email, string ticket);
}
Class Implementation of INotificationJob Interface
public class NotificationJob: DomainService, INotificationJob
{
private readonly ITicketRefManager _ticketRefManager;
private readonly IClientManager _clientManager;
private readonly IEmailManager _emailManager;
public NotificationJob(
ITicketRefManager ticketRefManager,
IClientManager clientManager,
IEmailManager emailManager,
)
{
_ticketRefManager = ticketRefManager;
_clientManager = clientManager;
_emailManager = emailManager;
}
public void Loop()
{
RecurringJob.AddOrUpdate(() => CheckTickets(), Cron.Minutely);
}
}
When I run the solution, I am presented with an error saying as shown:
Are there any other steps that I need to take to complete the Dependency Injection process? Or are the steps that I described flawed?
I'm not sure what you're trying to do with you "interface injecting", but you can try this if I understand correctly what you're trying to do :
Core Module
[...]
public override void PostInitialize()
{
var recurrentJobs = IocManager.Resolve<NotificationJob>();
RecurringJob.RemoveIfExists("JobName");
RecurringJob.AddOrUpdate("JobName", () => recurrentJobs.CheckTickets(), Cron.Minutely);
}
Your class
public class NotificationJob : ISingletonDependency
{
private readonly ITicketRefManager _ticketRefManager;
private readonly IClientManager _clientManager;
private readonly IEmailManager _emailManager;
public NotificationJob(
ITicketRefManager ticketRefManager,
IClientManager clientManager,
IEmailManager emailManager,
)
{
_ticketRefManager = ticketRefManager;
_clientManager = clientManager;
_emailManager = emailManager;
}
public void CheckTickets()
{
//Do something
}
}
Does it helps ?
I am starting to use Ninject in my MVC5 code-first app. Here's my NinjectWebCommon.cs:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<CMSContext>()
.ToSelf()
//.InSingletonScope();
.InRequestScope();
kernel.Bind<IExecutiveRepository>()
.To<ExecutiveRepository>();
kernel.Bind<IExecutiveSectionRepository>()
.To<ExecutiveSectionRepository>();
kernel.Bind<IExecutiveSectionMappingRepository>()
.To<ExecutiveSectionMappingRepository>();
kernel.Bind<IUserRepository>()
.To<UserRepository>();
kernel.Bind<IContentRepository>()
.To<ContentRepository>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
I tried .InSingletonScope() as well as .InRequestScope() but I still get the 'entity object cannot be referenced by multiple instances of IEntityChangeTracker' error.
Here is my Interface:
public interface IExecutiveRepository : IDisposable
{
IEnumerable<Executive> GetExecutives();
Executive GetExecutiveById(int executiveId);
void InsertExecutive(Executive executive);
void UpdateExecutive(Executive executive);
void DeleteExecutive(int executiveId);
void Save();
}
Here is my concrete:
public class ExecutiveRepository : IExecutiveRepository, IDisposable
{
private CMSContext context;
public ExecutiveRepository(CMSContext context)
{
this.context = context;
}
public IEnumerable<Executive> GetExecutives()
{
return context.Executives.ToList();
}
public Executive GetExecutiveById(int id)
{
return context.Executives.Find(id);
}
public void InsertExecutive(Executive executive)
{
context.Executives.Add(executive);
}
public void DeleteExecutive(int executiveId)
{
Executive executive = context.Executives.Find(executiveId);
context.Executives.Remove(executive);
}
public void UpdateExecutive(Executive executive)
{
context.Entry(executive).State = EntityState.Modified;
}
public void Save()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Here is the controller(top pertinent part):
public class ExecutiveController : Controller
{
private IExecutiveRepository executiveRepository;
private IUserRepository userRepository;
private IExecutiveSectionRepository executiveSectionRepository;
private IExecutiveSectionMappingRepository executiveSectionMappingRepository;
private IContentRepository contentRepository;
private Ninject.IKernel _kernel = new StandardKernel();
//[Inject]
public ExecutiveController()
{
executiveRepository = _kernel.Get<ExecutiveRepository>();
userRepository = _kernel.Get<UserRepository>();
executiveSectionRepository = _kernel.Get<ExecutiveSectionRepository>();
executiveSectionMappingRepository = _kernel.Get<ExecutiveSectionMappingRepository>();
contentRepository = _kernel.Get<ContentRepository>();
}
...
Not sure what I am doing wrong but upon adding a new 'Executive' it bombs... I do understand it's trying to use separate contexts and that's the problem, but I 'm just not sure how to fix it. Apparently, the line in the NinjectWebCommon.cs class:
kernel.Bind<CMSContext>()
.ToSelf()
//.InSingletonScope();
.InRequestScope();
Is supposed to be the fix, but it isn't...
any ideas/suggestions?
You should be using NUGET package Ninject.Web.Mvc if you aren't already. This configures your application ready to use Ninject, other than your bindings. It looks like you are reasonably familiar with the bindings side of things already from what I can see in your CreateKernel() method.
Once your bindings are in place, you should not be creating Kernels in your controllers, this is because the Ninject.Web.Mvc library configures Ninject to create your controllers for you under the hood. Therefore any dependencies that you add to them should be automatically resolved.
So, you can use constructor injection to resolve your dependencies:
public class ExecutiveController : Controller
{
private IExecutiveRepository ExecutiveRepository;
private IUserRepository UserRepository;
private IExecutiveSectionRepository ExecutiveSectionRepository;
private IExecutiveSectionMappingRepository ExecutiveSectionMappingRepository;
private IContentRepository ContentRepository;
public ExecutiveController(
IExecutiveRepository executiveRepository,
IUserRepository userRepository,
IExecutiveSectionRepository executiveSectionRepository,
IExecutiveSectionMappingRepository executiveSectionMappingRepository,
IContentRepository contentRepository)
{
// Set the field values
this.ExecutiveRepository = executiveRepository,
this.UserRepository = userRepository,
this.ExecutiveSectionRepository = executiveSectionRepository,
this.ExecutiveSectionMappingRepository = executiveSectionMappingRepository,
this.ContentRepository = contentRepository;
}
public ActionResult Index(int id)
{
// Use one of your dependencies...
var executive = this.executiveRepository.GetExecutiveById(id);
}
}
Or you can use the [Inject] attribute which has the same effect:
public class ExecutiveController : Controller
{
[Inject]
public IExecutiveRepository executiveRepository { get; set; }
[Inject]
public IUserRepository userRepository { get; set; }
[Inject]
public IExecutiveSectionRepository executiveSectionRepository { get; set; }
[Inject]
public IExecutiveSectionMappingRepository executiveSectionMappingRepository { get; set; }
[Inject]
public IContentRepository contentRepository { get; set; }
public ExecutiveController()
{
}
public ActionResult Index(int id)
{
// Use one of your dependencies...
var executive = this.executiveRepository.GetExecutiveById(id);
}
}
You're creating a kernel per controller.
InRequestScope only ensures one instance per request per kernel.
So you need to adapt your setup of the kernel so there's only one kernel per web application. See:
Ninject.Web.Mvc
Tutorial
Youtube
This may not answer the question. But I tend to use the IDbContextFactory that EF provides you with and do something like this:
public interface IDefaultContextFactory : IDbContextFactory<CMSContext> {}
public class DefaultContextFactory : IDefaultContextFactory
{
private readonly Lazy<CMSContext> lazyContext = new Lazy<CMSContext>(() => new CMSContext());
public CMSContext Create()
{
return lazyContext.Value;
}
}
Then you just bind that, and when you need the context you can do something like this:
public class ExecutiveRepository : IExecutiveRepository, IDisposable
{
private readonly CMSContext context;
public ExecutiveRepository(IDefaultContextFactory contextFactory)
{
this.context = contextFactory.Create();
}
}
I believe #BatteryBackupUnit is correct, I would also consider using the above pattern for contexts.
I am new to MVC so im fallowing a book example. But when I run the program it gives me the error: Error activating IProductRepository
No matching bindings are available, and the type is not self-bindable.
Activation path...
I have read a bunch of articles and other error like this one but none of them helped.
Why is this happening if everything is the same as in the book example? Please some help would be really appreciated.
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
}
protected override IController GetControllerInstance(RequestContext requestContext,
Type controllerType)
{
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();
}
}
Global.asax.cs
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
IProductRepository.cs
public interface IProductRepository
{
IQueryable<Product> Products { get; }
}
EFProductRepository.cs
public class EFProductRepository : IProductRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<Product> Products
{
get { return context.Products; }
}
}
public class EFDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
}
ProductController.cs
public class ProductController : Controller
{
private IProductRepository repository;
public ProductController(IProductRepository repoParam)
{
repository = repoParam;
}
public ViewResult List()
{
return View(repository.Products);
}
}
Change your method to accept the IKernel parameter:
private void AddBindings(IKernel kernel)
{
kernel.Bind<IProductRepository>().To<EFProductRepository>();
}
Then as Mike suggests call it from your NinjectControllerFactory constructor method:
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings(ninjectKernal);
}
I have a base class and a few derived classes. The base class contains a property that needs to be injected. How do I configure Unity to build my objects?
public class BaseService<T> where T : class
{
public T Entity { get; private set; }
[Dependency]
public IUnitOfWork UnitOfWork { get; private set; }
public BaseService(T obj)
{
this.Entity = obj;
}
}
public class ContactService : BaseService<Contact>
{
public ContactService(Contact obj) : base(obj)
{
}
public bool IsValid()
{
bool result = false;
// ...
return result;
}
public void AddContact()
{
if (!IsValid()) { throw new InvalidEntityException<Contact>(); }
try
{
this.UnitOfWork.BeginTransaction();
this.UnitOfWork.Add<Contact>(this.Entity);
this.UnitOfWork.CommitTransaction();
}
catch
{
this.UnitOfWork.RollbackTransaction();
}
}
}
How do I register this first of all and then how do I resolve ContactService since it has a constructor with arguments that can't be injected? Should I even be using Unity for this?
You can use UnitiContainer.BuildUp for injecting dependencies on an existing object. If you have a small predefined set of values for you constructor parameter you can use InjectionConstructor class to specify the value of the parameter during registration. Otherwise register a factory class with Unity and use it to create your services.
public class ContactServiceFactory
{
IUnitOfWork UnitOfWork { get; private set; }
public ContractServiceFactory(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
public ContactService Create(Contact obj)
{
return new ContractService(obj, unitOfWork);
}
}
I try to avoid that situation by structuring things like this:
public class ContactService : IContactService
{
private readonly IContactRepository repository;
private readonly IValidator<Contact> validator;
private readonly IUnitOfWork unitOfWork;
public ContactService(
IContactRepository repository,
IValidator<Contact> validator,
IUnitOfWork unitOfWork)
{
this.repository = repository;
this.validator = validator;
this.unitOfWork = unitOfWork;
}
public void Add(Contact contact)
{
if (!validator.IsValid(contact)) throw new ArgumentException();
try
{
unitOfWork.Start();
repository.Save(contact);
unitOfWork.Commit();
}
catch
{
unitOfWork.Rollback();
throw;
}
}
}
With this basic pattern in place, Unity can build up your service with all its dependencies and you don't get into the issue injecting the contact. The repository can be used as an abstraction or just directly use your favorite data access framework like EF, NHibernate, or plain old Ado.Net if that's how you roll.
Since the try catch stuff is repetative, you can use an extension method to compact your code like this:
public void Add(Contact contact)
{
if (!validator.IsValid(contact)) throw new ArgumentException();
unitOfWork.Execute(() => repository.Save(contact));
}
The extension method looks like this:
public static class UnitOfWorkExtensions
{
public static void Execute(this IUnitOfWork unitOfWork, Action action)
{
try
{
unitOfWork.Start();
action.Invoke();
unitOfWork.Commit();
}
catch
{
unitOfWork.Rollback();
throw;
}
}
}
More on this: http://www.agileatwork.com/refactoring-c-style/
The big advantage of structuring your code this way is that you can take advantage of Unity's interception mechanism and do lots of cool things like move the unit of work code to an aspect (attribute):
[UnitOfWork]
public void Add(Contact contact)
{
if (!validator.IsValid(contact)) throw new ArgumentException();
repository.Save(contact);
}
You can use a similar technique to add additional behaviors like logging, exception handling, and security.