Getting Ninject to work - c#

Clearly, I am missing something. I have an MVC application and have installed Ninject 3 and the MVC3 extensions (although I am running MVC4). I have a SiteSettings class that is referenced throughout the project, which looks like this:
public class SiteSettings
{
private static readonly Common.Logging.ILog Logger = Common.Logging.LogManager.GetCurrentClassLogger();
private static ObservableDictionary<string, string> settings;
private static bool Initialized = false;
private static DataPersister persister;
public static void Initialize()
{
if (Initialized) throw new InvalidOperationException("The SiteSettings object has already been initialized.");
persister = new DataPersister();
using (var u = persister.UnitOfWorkFactory.GetUnitOfWork())
{
var settingsList = u.SiteSettings.GetAll();
settings = new ObservableDictionary<string, string>(settingsList.ToDictionary(key => key.SiteSettingName, value => value.SiteSettingValue));
settings.OnChange += new kvpChangeEvent<string, string>(settings_OnChange);
}
Initialized = true;
}
static void settings_OnChange(object sender, odKVPChangeEventArgs<string, string> e)
{
using (var u = persister.UnitOfWorkFactory.GetUnitOfWork())
{
var setting = u.SiteSettings.GetByName(e.Key);
setting.SiteSettingValue = e.Value;
u.SiteSettings.Update(setting);
u.Save();
Logger.Info(i => i("Changed the '{0}' site setting from '{1}' to '{2}'.", e.Key, e.OldValue, e.Value));
}
}
private static int _ItemsPerPage;
public static int ItemsPerPage
{
get
{
return _ItemsPerPage;
}
set
{
_ItemsPerPage = value;
settings["itemsPerPage"] = value.ToString();
}
}
private static int _SessionLifeInMinutes;
public static int SessionLifeInMinutes
{
get
{
return _SessionLifeInMinutes;
}
set
{
_SessionLifeInMinutes = value;
settings["sessionLifeInMinutes"] = value.ToString();
}
}
private static string _DateFormat;
public static string DateFormat
{
get
{
return _DateFormat;
}
set
{
_DateFormat = value;
settings["defaultDateFormat"] = value;
}
}
}
I built a data persistence object like so:
public class DataPersister
{
public IUnitOfWorkFactory UnitOfWorkFactory { get; set; }
}
... and I have my NinjectWebCommon.cs looks like this:
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()
{
var 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<IUnitOfWork>().To<NHUnitOfWork>();
kernel.Bind<IUnitOfWorkFactory>().To<NHUnitOfWorkFactory>();
}
}
It seems to me I've met all my requirements for dependency injection. My Global.asax.cs Application_Start() looks like this:
protected void Application_Start()
{
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MonoRazorViewEngine());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.DefaultNamespaces.Add("MyApplication.Application.Controllers");
Initialize.Security();
SiteSettings.Initialize();
}
...and yet, my SiteSettings class always has a null IUnitOfWorkFactory when I try to collect the data I need.
What am I doing wrong? Everything seems to be as all the examples suggest it should be, but I get no love.
UPDATE
Using Bassam Mehanni's advice, I rewrote my DataPersister class to look like this:
public class DataPersister
{
private IUnitOfWorkFactory UnitOfWorkFactory;
public DataPersister(IUnitOfWorkFactory unitOfWorkFactory)
{
UnitOfWorkFactory = unitOfWorkFactory;
}
public IUnitOfWork GetUnitOfWork()
{
return UnitOfWorkFactory.GetUnitOfWork();
}
}
...but of course now my SiteSettings class complains about my parameterless constructor. What should I do about that?
UPDATE 2
Ok, continuing on, I rewrote my DataPersister class like so:
public class DataPersister
{
private static readonly Common.Logging.ILog Logger = Common.Logging.LogManager.GetCurrentClassLogger();
private IUnitOfWorkFactory UnitOfWorkFactory { get; set; }
public IUnitOfWork GetUnitOfWork()
{
return UnitOfWorkFactory.GetUnitOfWork();
}
[Inject]
public DataPersister(IUnitOfWorkFactory factory)
{
Logger.Info("Injected constructor called");
UnitOfWorkFactory = factory;
}
public DataPersister()
{
Logger.Info("Parameterless constructor called");
}
}
then I rewrote my SiteSettings class like so:
public class SiteSettings
{
private static readonly Common.Logging.ILog Logger = Common.Logging.LogManager.GetCurrentClassLogger();
private ObservableDictionary<string, string> settings;
private DataPersister persister;
private SiteSettings()
{
persister = new DataPersister();
using (var u = persister.GetUnitOfWork())
{
var settingsList = u.SiteSettings.GetAll();
settings = new ObservableDictionary<string, string>(settingsList.ToDictionary(key => key.SiteSettingName, value => value.SiteSettingValue));
settings.OnChange += new kvpChangeEvent<string, string>(settings_OnChange);
}
}
private static SiteSettings instance;
public static SiteSettings Instance
{
get
{
if (instance == null)
{
instance = new SiteSettings();
}
return instance;
}
}
private void settings_OnChange(object sender, odKVPChangeEventArgs<string, string> e)
{
using (var u = persister.GetUnitOfWork())
{
var setting = u.SiteSettings.GetByName(e.Key);
setting.SiteSettingValue = e.Value;
u.SiteSettings.Update(setting);
u.Save();
Logger.Info(i => i("Changed the '{0}' site setting from '{1}' to '{2}'.", e.Key, e.OldValue, e.Value));
}
}
private int _ItemsPerPage;
public int ItemsPerPage
{
get
{
return _ItemsPerPage;
}
set
{
_ItemsPerPage = value;
settings["itemsPerPage"] = value.ToString();
}
}
private int _SessionLifeInMinutes;
public int SessionLifeInMinutes
{
get
{
return _SessionLifeInMinutes;
}
set
{
_SessionLifeInMinutes = value;
settings["sessionLifeInMinutes"] = value.ToString();
}
}
private string _DateFormat;
public string DateFormat
{
get
{
return _DateFormat;
}
set
{
_DateFormat = value;
settings["defaultDateFormat"] = value;
}
}
}
Shouldn't this work? because it doesn't. The DataPersister class always gets called with the parameterless constructor. My kernel binding looks like this:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<NHUnitOfWork>();
kernel.Bind<IUnitOfWorkFactory>().To<NHUnitOfWorkFactory>();
}
Is there something else I am missing? This is getting very frustrating.

Static classes that depencend on none static classes is something you shouldn't do when using an IoC container. Instead you should create a none static class with a singleton lifetime.
Make your SiteSettings class none static.
Inject all dependencies e.g. IUnitOfWorkFactory into SiteSettings using constructor injection
Create a binding in singleton scope for SiteSettings
Get an instance of SiteSettings wherever you need access unsing constructor injection.
Example:
public class SiteSettings {
public SiteSettings(IUnitOfWorkFactory uowFactory) { .... }
....
}
public class INeedToAccessSiteSettings
{
public INeedToAccessSiteSettings(SiteSettings siteSettings) { .... }
}
kenrel.Bind<SiteSettings>().ToSelf().InSingletonScope();

Typically ninject will inject your service in a constructor or something, it doesn't magically turn all your interfaces to object instances at run time
e.g.:
public class MyController : Controller
{
private IServiceThatINeed _serviceThatINeed;
public MyController(IServiceThatINeed serviceThatINeed)
{
_serviceThatINeed = _serviceThatINeed;
}
}
in this case since you registered your kernel instance, mvc knows how to resolve this dependence and will pass an instance of an object that implement IServiceThatINeed (assuming that you told ninject how to resolve this dependency.
Now there might be instance where you will need to get a service without it being injected in a constructor by the mvc framework, in these instances (like the one you have here), you will need to use ServiceLocator
e.g.:
var myService = ServiceLocator.Current.GetInstance<IServiceThatINeed>()
to use the ServiceLocator, you need to add a reference to Microsoft.Practices.ServiceLocation
Hope that helps!

Related

Is it possible to have a singleton exist accross different projects within a solution?

I am attempting to communicate information between two different projects. One is a remoting server and the other a WPF application. I have created a singleton class but have noticed that each time one project calls the GetInstance method it creates a new instance of the singleton. Is it possible to have a singleton accross projects as it doesn't seem it is and if that is the case, why is that?
Below is my code for the singleton
public class CommunicationSingleton
{
private int jobCount = 0;
private Job jobInProgress;
private List<Job> jobs = new List<Job>();
private static CommunicationSingleton instance = new CommunicationSingleton();
static readonly object obj = new object();
private CommunicationSingleton() { }
public static CommunicationSingleton GetInstance()
{
lock (obj)
{
if (instance == null)
{
return instance = new CommunicationSingleton();
}
else
{
return instance;
}
}
}
public void AddJob(Job job)
{
jobs.Add(job);
}
public List<Job> GetJobs()
{
return jobs;
}
public void IncreaseJobCount(int jobCount)
{
this.jobCount += jobCount;
}
public int GetJobCount()
{
return jobCount;
}
public void JobInProgress(Job jobInProgress)
{
this.jobInProgress = jobInProgress;
}
public Job GetJobInProgress()
{
return jobInProgress;
}
}

using localization service GetAllLanguages from a component composer, incorrect DI?

I have an interface as below, which I use to add a specific language if it does not exist:
public interface IGetLanguagesService
{
void GetLanguages(ILocalizationService localization);
}
public class LanguageService : IGetLanguagesService
{
ILocalizationService _localizationService;
public void GetLanguages(ILocalizationService localization)
{
_localizationService = localization;
var currentLanguages = _localizationService.GetAllLanguages();
bool exists = false;
foreach (var currentLan in currentLanguages)
{
if (currentLan.IsoCode == "es-ES")
{
exists = true;
}
}
if (!exists)
{
AddLanguage(_localizationService);
}
}
public void AddLanguage(ILocalizationService localization)
{
var languageSE = new Language("es-ES") { CultureName = "es-ES", IsMandatory = true };
localization.Save(languageSE);
}
}
I want to use this at start-up so have created a component composer, which on Initialize() I want to call CallGetLanguages() but Im not entirely sure what should be in Initialize(), I think my DI may be wrong?
public class LanguagesComposer : ComponentComposer<LanguagesComponent>
{
public void Compose(Composition composition)
{
composition.Register<IGetLanguagesService>(Lifetime.Singleton);
composition.Register<ILocalizationService>(Lifetime.Singleton);
composition.Components().Append<LanguagesComponent>();
}
}
public class LanguagesComponent : IComponent
{
public void Initialize()
{
???????
}
public void Terminate()
{
throw new NotImplementedException();
}
IGetLanguagesService _getLanguagesService;
ILocalizationService _localization;
public void CallGetLanguages(IGetLanguagesService getLanguages, ILocalizationService localization)
{
_getLanguagesService = getLanguages;
_localization = localization;
_getLanguagesService.GetLanguages(localization);
}
}
You've passed ILocalizationService localization instance to LanguageService twice, pass it to constructor instead and use a constructor injection. The same issue with LanguagesComponent, pass all its dependencies to constructor instead of methods

Singleton class for an object with parameters

I realized that I should have only one instance of an object called StdSchedulerFactory running at a time. So far I instantiated the object like this
StdSchedulerFactory sf = new StdSchedulerFactory(properties);
And properties is a NameValueCollection.
How can I write a Singleton class for this object so that the variable sf will always have one instance throughout the program?
Part of the Singleton pattern is typically a private constructor, so that other classes can not make new instances.
The workaround for parameters coming from outside the class is to add a "Init" or "Configure" function:
public static void Configure(NameValueCollection properties)
{
}
Of course, if you forget to call this function, you may get behavior you don't want; so you may want to set a "Configured" flag or something like that so your other functions can react appropriately if this function has not yet been called.
Here is a basic Singleton implementation. It is not thread-safe.
public sealed class StdSchedulerFactory
{
private static readonly StdSchedulerFactory instance;
private NameValueCollection _properties;
private StdSchedulerFactory(NameValueCollection properties)
{
_properties = properties;
}
public static StdSchedulerFactory GetInstance(NameValueCollection properties)
{
if (instance == null)
{
instance = new StdSchedulerFactory(properties);
}
else
{
return instance;
}
}
}
this is my two favorite way implementing simple singleton pattern. The second one is just easier when debugging :)
public sealed class SingletonOne
{
private static readonly Lazy<SingletonOne> instance = new Lazy<SingletonOne>(() => new SingletonOne());
private Lazy<Controller> controller = new Lazy<Controller>(() => new Controller(properties));
private static object properties = null;
public static SingletonOne Instance { get { return instance.Value; } }
public Controller GetController(object properties)
{
SingletonOne.properties = properties;
return this.controller.Value;
}
}
public sealed class SingletonTwo
{
private static readonly SingletonTwo instance = new SingletonTwo();
private Controller controller;
private static object properties = null;
public static SingletonTwo Instance
{
get
{
return SingletonTwo.instance;
}
}
public Controller GetController(object properties)
{
SingletonTwo.properties = properties;
if(this.controller == null)
{
this.controller = new Controller(SingletonTwo.properties);
}
return this.controller;
}
}
public class Controller
{
public Controller(object properties) { }
}

NSubstitute and Unity

I am currently trying to learn DI & Mocking, with Unity and NSubstitute. I am also using an automocking extension taken from this question: Is this possible with Unity (Instead of Castle Windsor)?
In my unit test below I am trying to set an NSubstitute return value of 10 from my method Add(). However when debugging through the controller call the assigned value is the default 0 rather than the expected 10. The proxy does not seem to be intercepting the method call.
I suspect this is caused by not registering my Types/container correctly, anybody able to point me in the right direction?
[TestFixture]
public class ApplicationControllerTests
{
private IUnityContainer _container;
private ApplicationController _controller;
private ISampleService _sampleService;
[SetUp]
public void SetUp()
{
_container = new UnityContainer().AddExtension(new AutoMockingContainerExtension());
_controller = _container.Resolve<ApplicationController>();
_sampleService = _container.Resolve<ISampleService>();
}
[Test]
public void TestSampleService()
{
// This line is not working
_sampleService.Add(Arg.Any<int>(), Arg.Any<int>()).Returns(10);
var result = _controller.Index();
_sampleService.Received().Add(Arg.Any<int>(), Arg.Any<int>());
}
}
public class AutoMockingContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer _container;
public AutoMockingBuilderStrategy(IUnityContainer container)
{
_container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !_container.IsRegistered(key.Type))
context.Existing = CreateSubstitute(key.Type);
}
private static object CreateSubstitute(Type type)
{
return Substitute.For(new[] { type }, null);
}
}
}
And my controller code
public class ApplicationController : BaseController
{
private readonly ISampleService _sampleService;
public ApplicationController(ISampleService sampleService)
{
_sampleService = sampleService;
}
public ActionResult Index()
{
var result = _sampleService.Add(2, 3);
// result is 0, expected 10 ??
return View();
}
}
public interface ISampleService
{
int Add(int first, int second);
}
public class SampleService : ISampleService
{
public int Add(int first, int second)
{
return first + second;
}
}
Actually Tormod is right the problem is that the AutoMockingBuilderStrategy returns a different mock instance every time when somebody requests an ISampleService form the container.
So there is a bug in my original implementation namely the AutoMockingBuilderStrategy doesn't store the created mocks:
Here is a fixed version:
public class AutoMockingContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer container;
private readonly Dictionary<Type, object> substitutes
= new Dictionary<Type, object>();
public AutoMockingBuilderStrategy(IUnityContainer container)
{
this.container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !container.IsRegistered(key.Type))
{
context.Existing = GetOrCreateSubstitute(key.Type);
context.BuildComplete = true;
}
}
private object GetOrCreateSubstitute(Type type)
{
if (substitutes.ContainsKey(type))
return substitutes[type];
var substitute = Substitute.For(new[] {type}, null);
substitutes.Add(type, substitute);
return substitute;
}
}
}
I suspect that you are dealing with two different instances of ISampleService, created in lines 2 and 3 of Setup, respectively.
Could you, for test, make the _sampleServie field public and in the third Setup() line try
_sampleService = _controller._sampleService;

Sourcing AppSettings from database & cache

At my office, it has been deemed that we are to put our AppSettings for the Web.Config in the database. As such, I created the following, but have some doubts about a couple aspects of the code.
So my question is:
The line containing "Cache cache = new Cache()" in the UTILITY class is probably wrong because it creates a NEW cache object.
Q: So, what should I be doing for that line?
...any help is appreciated.
The overall objective was to be able to make a call like this:
Utility.GetConfigurationValue(ConfigurationSection.AppSettings, "myVariable");
...and have it retrieve from the cache or the database auto-magically.
THE UTILITY CODE:
public static class Utility
{
#region "Configurations"
public static String GetConfigurationValue(ConfigurationSection section, String key)
{
Configurations config = new Configurations();
Cache cache = new Cache(); // <--- This is probably wrong!!!!
if (!cache.TryGetItemFromCache<Configurations>(out config))
{
config.List(SNCLavalin.US.Common.Enumerations.ConfigurationSection.AppSettings);
cache.AddToCache<Configurations>(config, DateTime.Now.AddMinutes(15));
}
var result = (from record in config
where record.Key == key
select record).FirstOrDefault();
return (result == null) ? null : result.Value;
}
#endregion
}
THE EXTENSION CODE:
public static class Extensions
{
#region "System.Web.Caching"
public static void Remove<T>(this Cache cache) where T : class
{
cache.Remove(typeof(T).Name);
}
public static void AddToCache<T>(this Cache cache, object item, DateTime absoluteExpiration) where T : class
{
T outItem = null;
if (cache.TryGetItemFromCache<T>(out outItem))
return;
cache.Insert(typeof(T).Name,
item,
null,
absoluteExpiration,
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Normal,
null);
}
public static bool TryGetItemFromCache<T>(this Cache cache, out T item) where T : class
{
item = cache.Get(typeof(T).Name) as T;
return item != null;
}
#endregion
}
THE LIST-CLASS CODE:
public class Configurations : List<Configuration>
{
#region CONSTRUCTORS
public Configurations() : base()
{
initialize();
}
public Configurations(int capacity) : base(capacity)
{
initialize();
}
public Configurations(IEnumerable<Configuration> collection) : base(collection)
{
initialize();
}
#endregion
#region PROPERTIES & FIELDS
private Crud _crud;
#endregion
#region EVENTS
#endregion
#region METHODS
private void initialize()
{
_crud = new Crud("CurrentDbConnection");
}
public Configurations List(ConfigurationSection section)
{
using (DbCommand dbCommand = _crud.Db.GetStoredProcCommand("spa_LIST_SecConfiguration"))
{
_crud.Db.AddInParameter(dbCommand, "#Section", DbType.String, section.ToString());
_crud.List(dbCommand, PopulateFrom);
}
return this;
}
public void PopulateFrom(DataTable table)
{
this.Clear();
foreach (DataRow row in table.Rows)
{
Configuration instance = new Configuration();
instance.PopulateFrom(row);
this.Add(instance);
}
}
#endregion
}
THE ITEM-CLASS CODE:
public class Configuration
{
#region CONSTRUCTORS
public Configuration()
{
initialize();
}
#endregion
#region PROPERTIES & FIELDS
private Crud _crud;
public string Section { get; set; }
public string Key { get; set; }
public string Value { get; set; }
#endregion
#region EVENTS
#endregion
#region METHODS
private void initialize()
{
_crud = new Crud("CurrentDbConnection");
Clear();
}
public void Clear()
{
this.Section = "";
this.Key = "";
this.Value = "";
}
public void PopulateFrom(DataRow row)
{
Clear();
this.Section = row["Section"].ToString();
this.Key = row["Key"].ToString();
this.Value = row["Value"].ToString();
}
#endregion
}
You have correctly identified the problem - the current code creates a new Cache instance on each call to GetConfigurationValue which defeats the purpose of caching. You need to make the Cache instance static rather than creating a new instance each time.
public static class Utility
{
private static Cache cache = new Cache(); // Static class variable
#region "Configurations"
public static String GetConfigurationValue(ConfigurationSection section, String key)
{
Configurations config = new Configurations();
// Cache cache = new Cache(); --- removed
...
}
}
ADDENDUM TO ANSWER:
I did (in fact) need to point the cache variable to something else. It wouldn't work until I did the following in the Utility class.
private static Cache cache = System.Web.HttpRuntime.Cache;

Categories