I am trying to use property Setter injection method, in the FilterAttribute class
Below is my AttributeFilter
public class HasIfNoneMatchAttribute : ActionFilterAttribute
{
[Inject]
public ICorporationRepository _corporationRepository { set; private get; }
public override void OnActionExecuting(HttpActionContext actionContext)
{
var request = actionContext.Request;
ICollection<EntityTagHeaderValue> etagsFromClient = request.Headers.IfNoneMatch;
if (etagsFromClient.Count > 0)
{
EntityTagHeaderValue etag = new EntityTagHeaderValue(this._corporationRepository.GetETagForCorporationRequirement("param1", "param2", "param3"));
if (etagsFromClient.Contains(etag))
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.NotModified);
// SetCacheControl(context.Response);
}
}
base.OnActionExecuting(actionContext);
}}
}
I am already using constructor injection in the project. which works fine.
Below is part of my NinjectWebCommon.cs file
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICorporationRepository>().To<CorporationRepository>();
}
Property is not getting injected, and I get the error -
System.NullReferenceException: Object reference not set to an instance of an object.
What am I missing?
Related
So I Have this class:
public class GeneralService : IDisposable
{
private readonly LoggingService _logginService;
private readonly DataService _dataService;
private readonly IServiceProvider _serviceProvider;
public GeneralService(LoggingService loggingService, DataService dataService, IServiceProvider serviceProvider)
{
_logginService = loggingService;
_dataService = dataService;
_serviceProvider = serviceProvider;
var eventBusProvider = serviceProvider.getService<eventBusProvider>();
eventBusProvider.RegisterForNotification(this, EventTypes.Exception, HandleException);
}
public void Dispose()
{
var eventBusProvider = _serviceProvider.GetService<eventBusProvider>();
eventBusProvider.UnRegisterForNotification(this);
}
public void Execute(Action action)
{
LoggingService loggingService = _serviceProvider.GetService<loggingService>();
StopWatch watch = new StopWatch();
watch.Start();
loggingService.LogInformation("Start Executing");
try
{
action();
}
catch (Exception exception)
{
loggingService.LogException(exception);
return;
}
watch.stop();
_dataService.CreateLog($"{nameof(GeneralService)} - {nameof(Execute)}: {watch.ElapsedMillieseconds}");
}
private void HandleException(Exception exception)
{
var loggingService = new LoggingService();
_dataService.CreateLog(exception);
loggingService.LogInformation("Ëxception was logged");
}
}
And I have 2 problems, I can't describe the responsibilities of this class and I'm not sure exactly how can I refactor it according to industry best practices, any help would be great.
thanks in advance.
I'm trying to use Autofac to register a service into Xamarin.Forms (netstandard2.0)
here's my code:
SqliteManager.cs
public interface ISqliteManager
{
void test();
}
public class SqliteManager : ISqliteManager
{
private readonly string _path;
public SqliteManager()
{
_path = "test";
}
public void test()
{
Console.Write(_path);
}
}
App.xaml.cs
public partial class App : Application
{
public App()
{
InitializeComponent();
ViewModelLocator.RegisterDependencies();
ViewModelLocator.Resolve<ISqliteManager>().test();
}
}
ViewModelLocator.cs
public static class ViewModelLocator
{
private static IContainer _container;
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterType<SqliteManager>().As<ISqliteManager>().SingleInstance();
_container?.Dispose();
_container = builder.Build();
}
public static T Resolve<T>()
{
return _container.Resolve<T>();
}
}
it's seems ok, but i get this error when i try to resolve the service in app.xaml.cs:
Registration: Activator = SqliteManager (ReflectionActivator),
Services = [Tracker.Managers.Interfaces.ISqliteManager], Lifetime =
Autofac.Core.Lifetime.RootScopeLifetime, Sharing = Shared, Ownership =
OwnedByLifetimeScope ---> No constructors on type
'Tracker.Managers.SqliteManager' can be found with the constructor
finder 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'.
but sqlitemanager has a constructor!
The ViewModel (set via AutoWireViewModel="True") of my Shell / MainWindow requests a dependency which gets loaded in a module at startup using the ConfigurationModuleCatalog.
Because the Shell is initialzed before the modules, the DI container obviously can't resolve it, so the application crashes.
public class MainWindowViewModel : BindableBase
{
// Cannot resolve IService
public MainWindowViewModel(IService service)
{
}
}
I already tried the two approaches of this post, but both didn't worked.
I tried it this way:
public interface IShellService
{
int NumberOfLoadedModules { get; }
void FlagModuleAsLoaded();
}
public class ShellService : IShellService
{
private readonly IModuleCatalog _moduleCatalog;
public ShellService(IModuleCatalog moduleCatalog)
{
_moduleCatalog = moduleCatalog;
}
public int NumberOfLoadedModules { get; private set; }
public void FlagModuleAsLoaded()
{
NumberOfLoadedModules++;
if (NumberOfLoadedModules != _moduleCatalog.Modules.Count())
return;
InitializeShell();
}
private static void InitializeShell()
{
Application.Current.MainWindow.Show();
}
}
internal class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return null;
}
protected override void InitializeShell()
{
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.RegisterInstance<IShellService>(new ShellService(ModuleCatalog), new ContainerControlledLifetimeManager());
}
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}
}
Usage
public abstract class ModuleBase : IModule
{
private readonly IShellService _shellService;
protected ModuleBase(IShellService shellService)
{
_shellService = shellService;
}
public void Initialize()
{
InitializeInternal();
FlagAsLoaded();
}
public abstract void InitializeInternal();
public void FlagAsLoaded()
{
_shellService.FlagModuleAsLoaded();
}
}
public class FooModule : ModuleBase
{
IUnityContainer _container;
public MusicUIModule(IUnityContainer container, IShellService shellService) : base(shellService)
{
_container = container;
}
public override void InitializeInternal()
{
_container.RegisterType<IService, Service>();
}
}
It starts counting the modules and then the application crashes because of the same reason.
If the approach above isn't fitting for my purpose, how could that problem be solved?
Thanks!
I tried to implement Haukinger's suggestion and did it this way which works just fine:
// Factory --------------------------------------------------------
public interface IDependencyFactory
{
IService GetService();
}
public class DependencyFactory : IDependencyFactory
{
private readonly IUnityContainer _container;
public DependencyFactory(IUnityContainer container)
{
_container = container;
}
public IService GetService()
{
return _container.Resolve<IService>();
}
}
// PubSubEvent ------------------------------------------------------
public class AllModulesLoaded : PubSubEvent
{
}
// Bootstrapper -----------------------------------------------------
internal class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow.Show();
}
protected override void InitializeModules()
{
base.InitializeModules();
// Publishing event to tell subscribers that the modules are loaded
var eventAggregator = Container.Resolve<IEventAggregator>();
eventAggregator?.GetEvent<AllModulesLoaded>().Publish();
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
// ...
Container.RegisterType<IDependencyFactory, DependencyFactory>();
}
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}
}
// ViewModel ---------------------------------------------------------
public class MainWindowViewModel : BindableBase
{
private IService _service;
private readonly IEventAggregator _eventAggregator;
private readonly IDependencyFactory _dependencyFactory;
public MainWindowViewModel(IEventAggregator eventAggregator, IDependencyFactory dependencyFactory)
{
_eventAggregator = eventAggregator;
_dependencyFactory = dependencyFactory;
_eventAggregator.GetEvent<AllModulesLoaded>().Subscribe(OnAllModulesLoaded);
}
private void OnAllModulesLoaded()
{
var service = _dependencyFactory.GetService();
if (service != null)
_service = service ;
_eventAggregator.GetEvent<AllModulesLoaded>().Unsubscribe(OnAllModulesLoaded);
}
}
I'd hide the dependency of the shell behind a factory/provider and then create/fetch it when the last module is loaded. Your shell's view model subscribes to a AllModulesLoaded event that's fired from your bootstrapper's InitializeModules when base.InitializeModules returns to get notified that the dependency is available. Or the factory/provider subscribes to the event and the shell polls it, depending on how you want to use the dependency.
My Setup:
Visual Studio 2013
Web Forms/MVC project
C#
Ninject 3.2.0.0
Entity Framework
I have a Web Forms/MVC hybrid project that uses Ninject for its IoC containter. I've no problems with Ninject until today. The problem I ran into is that I can't get Ninject to new up some objects whenever I use a class. Here is some code that works:
// Master1.master
namespace TestCode
{
public partial class Master1 : MasterPage
{
[Inject]
public FooController Foo { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
// Do some setup logic.
Foo.Bar();
}
}
}
Now here is some code that doesn't work using a class:
// Master1.master
namespace TestCode
{
public partial class Master1 : MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
new Wrapper().SomeMethod();
}
}
}
// Wrapper.cs
namespace TestCode
{
public class Wrapper
{
[Inject]
public FooController Foo { get; set; }
public void SomeMethod()
{
// Do some setup logic.
Foo.Bar();
}
}
}
My problem is that when I execute SomeMethod(), Foo is null. Why is this and what can I do to get Ninject to new up Foo?
Okay - I got it working now. Thanks everyone! I needed to add a binding my NinjectWebCommon class like so:
public static class NinjectWebCommon
{
private static readonly Bootstrapper Bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
Bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
Bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// Needed to add this binding.
kernel.Bind<IWraper>().To<Wraper>().InRequestScope();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
}
}
How to inject dependency into CompositeControl?
I tried the following approach - MyServerControl's Calculate is still null.
Thanks!
public class MyServerControl : CompositeControl
{
private TextBox TextBox1;
private TextBox TextBox2;
private Label Label1;
[Inject] // **** This is null ****
public ICalculate Calculate { get; set; }
protected override void CreateChildControls()
{
TextBox1 = new TextBox {ID = "TextBox1", Text = "1"};
Controls.Add(TextBox1);
TextBox2 = new TextBox {ID = "TextBox2", Text = "2"};
Controls.Add(TextBox2);
var button1 = new Button {ID = "Button1", Text = "Calculate"};
button1.Click += button1_Click;
Controls.Add(button1);
Label1 = new Label {ID = "Label1"};
Controls.Add(Label1);
}
private void button1_Click(object sender, EventArgs e)
{
int value1 = Int32.Parse(TextBox1.Text);
int value2 = Int32.Parse(TextBox2.Text);
Label1.Text = "Result:" + Calculate.Add(value1, value2);
}
}
public interface ICalculate
{
int Add(int x, int y);
}
public class Calculate : ICalculate
{
public int Add(int x, int y)
{
return x + y;
}
}
Default Ninject.Web.Common Bootstrapper from NuGet:
using System.Net.NetworkInformation;
[assembly: WebActivator.PreApplicationStartMethod(typeof(NinjectDemo.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(NinjectDemo.App_Start.NinjectWebCommon), "Stop")]
namespace NinjectDemo.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
IKernel kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICalculate>().To<Calculate>().InSingletonScope();
}
}
}
Updated:
I'm not able to get instance to kernel in Page_Load. Am I missing something?
<my:MyServerControl ID="MyServerControl1" runat="server" />
public partial class Default : Page
{
[Inject]
public ICalculate _calculate { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
kernel.Inject(MyServerControl1); // kernel is not available
}
}
I think you could just use the feature that satisfies dependencies on an existing object. In this particular case, in any context your control is used, you just call
kernel.Inject( myControl );
where myControl is an existing instance of your composite control. This has to be called from the code behind, somewhere in the pipeline where the instance is already created. Page_Load would most probably be fine.
Edit: there are numerous ways to be able to resolve anywhere in your application. You could for example have a global service locator. But since you are using the Bootstrapper, you should be able to resolvd your kernel anywhere
var kernel = (IKernel)Bootstrapper.Container;
Your Default page doesn't know about NinjectWebCommon class existence. It also cannot know about the kernel variable which is a NinjectWebCommon.CreateKernel() method's member. The simplest solution is the following:
public static class NinjectWebCommon
{
...
private static IKernel kernel;
public static IKernel CreateKernel()
{
if(kernel != null)
return kernel;
kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
...
}
public partial class Default : Page
{
[Inject]
public ICalculate _calculate { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
NinjectWebCommon.CreateKernel().Inject(MyServerControl1);
}
}
The other way would be to use Ninject magic. Your application class would probably need to inherit from a class provided by Ninject. In MVC it's a NinjectHttpApplication class, which overrides the bootstrapper. Than you could probably go with Wiktor's answer.
Honestly I don't like that Ninject magic, as it sometimes doesn't work for me and than it's very hard to find out why. In my MVC application I ended up creating my own ConfrollerFactory, which injected the dependencies explicitly. It also may be a pain if you want to change your IOC container.
you need to register your Ioc config, see example:
public static void RegisterIoc(HttpConfiguration config)
{
var kernel = new StandardKernel(); // Ninject IoC
kernel.Bind<IMyService>().To<MyService>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.GetAll(serviceType);
}
}
Add this class in your App_start folder, and then write in Global.asax.cs:
// Tell WebApi to use our custom Ioc (Ninject)
IocConfig.RegisterIoc(GlobalConfiguration.Configuration);