How to prevent Dependency objects to be instantiated somewhere else? - c#

So basicly if i have a service MyMonkeyService which implements interface IMyMonkeyService and i make a register a DI object like :
SimpleIOC.Default.Register(Of IMyMonkeyService, MyMonkeyService)
How do i make sure that some developer after me not going to create new instance of MyMonkeyService somewhere in the application? I cant make Service's constructor private or protected, because then DI wouldnt work, if i create a Init() method on the service, it will still be available to the "new developer".

How about making MyMonkeyService a singleton?
You would have an implementation like this:
public class MyMonkeyService : IMyMonkeyService
{
private static MyMonkeyService _instance;
public static IMyMonkeyService Instance
{
get
{
// Gets the singleton if created, otherwise create a new instance
return _instance != null ? _instance : (_instance = new MyMonkeyService());
}
}
// Private constructor
private MyMonkeyService()
{
// ...
}
}
I don't know what DI framework you are using, but you would end up with something like the following:
SimpleIOC.Default.Register(Of IMyMonkeyService, MyMonkeyService.Instance);
Everytime your service is injected, the same instance will be used.

If you require multiple instances, you cant. Everything you make available to the DI container will be available for another developer.
You can write an analyzer though, which checks for instantiation of MyMonkeyService and emits an appropriate error.
This or this may help you getting started.
Roselyn Analyzers let you write code analysis tools that check the code for specific patterns and can emit errors and warnings accordingly. You can even define fixes for that pattern.

Related

Is it ok to pass Ninject Web.Common UseNinjectMiddleware a lambda which returns a kernel instance?

Why does UseNinjectMiddleware take a lambda instead of a container instance?
Is it OK to do this?
var container = CreateKernel();
app.UseNinjectMiddleware(() => container);
instead of this:
app.UseNinjectMiddleware(() => CreateKernel);
My container instance in the first snippet is used to resolve dependencies in another part of my app. Does the Ninject Middleware need to be able to create it's own instances which it can modify, muck-around with and re-create at will? If not, I would like to avoid building the dependency tree more than once, hence why I'm wondering if it's OK for the lambda to just return the instance.
There are a couple of things to note:
The OwinBootstrapper component will load any defined NinjectModule's after calling the passed in Func<IKernel> so you need to take care that you do not load anything twice. see here
The Bootstrapper component calls Dispose on IKernel so you will need to be sure you do not attempt to access the instance after a shutdown has been initiated. see here
You can almost get to the underlying Kernel right after it has been created, maybe you would prefer to raise a PR to make it available?
Currently OwinAppBuilderExtensions defines
public const string NinjectOwinBootstrapperKey = "NinjectOwinBootstrapper";
which it uses to store the run-time instance of OwinBootstrapper
app.Properties.Add(NinjectOwinBootstrapperKey, bootstrapper);
OwinBootstrapper holds a private reference to the run-time instance of the Bootstrapper component and the Bootstrapper instance in turn exposes a reference to the run-time instance of IKernel
public IKernel Kernel
{
get { return kernelInstance; }
}
So a little PR adding
public IKernel Kernel
{
get
{
this.bootstrapper.Kernel;
}
}
to OwinBootstrapper could make the underlying IKernel available to your code via app.Properties after the call to app.UseNinjectMiddleware(() => container);.

Nancy create singleton with constructor parameters

I'm using Nancy with TinyIoC to solve the dependencies.
One dependency in particular needs to be application-lifecycle singleton.
If I do it with a default constructor it works:
container.Register<IFoo, Foo>().AsSingleton(); // WORKS
but if i try this with some arguments on the contructor it does not:
container.Register<IFoo>((c, e) => new Foo("value", c.Resolve<ILogger>())).AsSingleton();
// FAILS with error "Cannot convert current registration of Nancy.TinyIoc.TinyIoCContainer+DelegateFactory to singleton"
Whithout .AsSingleton(), it works again, but I don't get a singleton:
container.Register<IFoo>((c, e) => new Foo("value", c.Resolve<ILogger>()));
// Works, but Foo is not singleton
Any Ideas? I think the mistake should be obvious but I can't find it.
I've used up all my google-foo.
EDIT
The code runs here:
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
// here
}
}
What you're doing there is telling TinyIOC "every time you want one of these, call my delegate", so if you want to use that method you have to handle the singleton aspect yourself.
Unless you particularly need the deferred creation it's easier to do:
container.Register<IFoo>(new Foo("value", c.Resolve<ILogger>()));
That will then always use that instance whenever you want an IFoo.

DI/IoC with a Singleton Logger class

We are using an in house simple Logger class for our application's logging tasks (.NET 3.5).
The logger code is pretty old, and is designed similarly to this:
public class Logger : ILogger
{
private ILogger instance;
private static ILogger Instance
{
// Initialized on first use.
get { return instance; }
}
public static void Debug(string msg)
{
instance.Debug(msg);
}
public static void Error(string msg)
{
....
}
}
The instance itself is being initialized on first usage (lazily).
This is not a Singleton according to its strict "by the book" implementation, but nonetheless, the access to this class from all calling code is a static access.
I would like, for testing purposes and for other architectural reasons, to be able to replace the internal instance with something else (inject it).
How can i achieve this easily? we are not using any IoC container at the moment, but i would not want to expose a setter to the Instance property since that would defeat the whole Singleton like design.
Any suggestions on how to come up with a solution for this?
Consider using Fakes Framework for testing purposes. You could stub the call to static method with something like this
ShimLogger.Instance = () => new LoggerMock();
In case of .net 3.5 you can use Moles Framework to stub static method call. Configuration code will look something like:
MLogger.Instance = () => new LoggerMock();
It would require to make static method Instance public, but after this configuration every call to static method will return your mocked instance.
Indeed, a setter does not sound like a good choice.
Instead, I would consider two possible approaches. First, an explcit configuration method:
public class Logger : ILogger {
public void ConfigureLogger( ILogger logger ) {
this.instance = logger;
}
}
An advantage of such approach is that the intention is clear plus you have to call this method in an explicit way.
Another option would be to allow one to pass a type of your logger in your configuration:
<appSettings>
<add key="loggerType" value="The.Type.From, Some.Assembly" />
</appSettings>
Then, in your Logger class you rewrite the initialization routine so that if the configuration parameter is present, you prefer the type provided in the configuration OVER the default type.
An advantage of such approach is that you can reconfigure the client with the configuration change with no changes to the code.
Anyway, IoC containers don't bite. Introduce one as it pays off in a long term.
I wouldn't roll your own. I use the Enterprise Library for almost all my logging needs. It works on desktop and asp.net projects. Asp.net can be a bit more problematic since you have to deal with security on the server but I've done it.
http://entlib.codeplex.com/
People also like Log4Net but I've never used it so I can't comment on it.
I would modify the code using the Logger. Instead of accessing the logger through Logger.Instance, pass in the desired instance of the logger into the object. Then in your factories and/or composition root you pass Logger.Instance as the source of the logger in your production code, and in your unit tests it is easy to use a mock logger.
public class Foo
{
private readonly ILogger logger;
public Foo(ILogger logger)
{
if (logger == null)
throw new ArgumentNullException("logger");
this.logger = logger;
}
public void Func()
{
try
{
// do something
}
catch (Exception ex)
{
// call the provided logger dependency
this.logger.WriteError(ex);
// not the static singleton property
Logger.Instance.WriteError(ex);
}
}
}
Another idea would be to make an internal setter for your Instance property and use the InternalsVisibleTo attribute to make the internal setter visible to your test assembly. Note that if the assembly that contains your logger is strong named, then you must specify the PublicKey in the InternalsVisibleTo attribute. Obviously this is most helpful (in the sense of not letting other developers accidentally - or on purpose - setting Instance to something else) if your logger lives in is own assembly or in some kind of infrastructure assembly where most development/logging is NOT taking place.

Dependency Injection - right place to inject

Looking at this answer on SO, I am a bit confused by the following "principle":
Apply the Hollywood Principle
The Hollywood Principle in DI terms says: Don't call the DI Container, it'll call you.
Never directly ask for a dependency by calling a container from within
your code. Ask for it implicitly by using Constructor Injection.
But what if I have a repository class in my DAL, and I want to supply this instance to an object which is created when a TCP/IP client connects? At what place should I make the injection?
Right now, I have something like:
// gets created when a new TCP/IP client is connected
class Worker
{
private readonly IClient client;
public Worker(IClient client)
{
// get the repository
var repo = IoC.GetInstance<IClientMessagesRepo>();
// create an object which will parse messages
var parser = new MessageParser(client);
// create an object which will save them to repo
var logger = new MessageLogger(parser, repo);
}
}
I obviously cannot create this instance when my app is started. So where do I inject the repo?
Thanks a lot!
You should strive to only call IoC.GetInstance() once.
Since you cannot create the Worker at startup, you should instead create a WorkerFactory and have the DI container inject the dependency into that:
public class WorkerFactory
{
private readonly IClientMessagesRepo clientMessagesRepo;
public WorkerFactory(IClientMessagesRepo clientMessagesRepo)
{
this.clientMessagesRepo = clientMessagesRepo;
}
public Worker Create(IClient client)
{
return new Worker(client, clientMessagesRepo);
}
}
Move IClientMessagesRepo to your constructor arguments:
public Worker(IClient client,IClientMessagesRepo clientMessagesRepo)
Now of course this only moves the problem a bit, to the point where the worker is created. Of course at some point calls into the IoC container are necessary. But in those cases I'd rather pass in the container in a parameter than access it from a static property. Or use some kind of factory.
Have IClientMessagesRepo in your arguments, and let the IoC fill that for you:
public Worker(IClient client, IClientMessagesRepo repo)
{
[...]
}
Obviously, your constructor should do a little more than just create a couple local variables, but you get the idea.
As I understand you have the repository in your IOC container, but not the IClient. Assuming that you have access to the IOC container at the time you create your worker class, and assuming that you are using StructureMap you can write:
IClient concreteClient = ...;
worker = container.Using<IClient>(concreteClient).GetInstance<Worker>();
That way you tell StructureMap to use a specific IClient instance, but obtain the other dependencies from the repository.
note: It is some time since I last used StructureMap, so perhaps the code is not 100% correct, but the concept is there, you can provide a concrete dependency when creating a component.

Unity - resolving without resolve()

I would like to just markup a property with an attribute [DoInjection] and have unity do the injection. I don't want to have to use prop = Unity.Resolve(type). Thats a pain and messy. Does unity provide attributes to do this or do I have to build my own?
Edit: register in App.Main
ISessionFactory sf = new SessionFactory();
container.RegisterType<IRepository, CustomerRepository>(new InjectionConstructor(sf.CurrentUoW));
container.RegisterInstance<IUnitOfWork>(sf.CurrentUoW);
Using [Dependancy] on IUnitOfWork propery in ClassX other class but it's always null. Do I need to build ClassX instance using Unity to get this to work? It looks like I do have to. I don't like that.
Unity has a DependencyAttribute you can use for this:
public class MyObject
{
private SomeOtherObject _dependentObject;
[Dependency]
public SomeOtherObject DependentObject
{
get { return _dependentObject; }
set { _dependentObject = value; }
}
}
http://msdn.microsoft.com/en-us/library/ff650198.aspx
Based on your question, it sounds like you might be trying to use Unity in the wrong spot and your design sense was telling you it didn't feel right. You should only see Unity where you bootstrap your application. That's your Main method in a console app or Global.asax in a web or wcf app. The idea is to keep relying on dependencies all the way up the chain until you get to where you bootstrap and resolve just that one top level object using your IoC container. In a console app, I do this:
class Program
{
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container
.AddExtension(new ConfigureForConsole(args))
.Resolve<MyApplication>()
.Execute();
}
}
}
http://www.agileatwork.com/console-application-with-ioc/
In this case, MyApplication is my top level object (it doesn't need to be an interface here). The ConfigureForConsole is just a one-off custom container extension that has all the RegisterType lines in there. Alternatively you could initialize the container from App.Config here. The idea though is that your Main method has almost nothing in it. Another benefit of this approach is that it makes your code more portable. I find that console apps usually turn into windows services and keeping things clean here makes that transition pretty painless.

Categories

Resources