How do i handle static classes while using IOC - c#

I just started migrating my web application to fully use Windsor IOC. Here is a little problem I am encountering;
I have couple of static classes which I used to store some application level global values
EG (Simplified version of the class):
public static class SiteInfo
{
public static Language Language = (Language)byte.Parse(SiteInfo.Val("language"));
public static string Code = Site.Code;
public static string Name = Site.Name;
public static SiteCachedData CachedData { get; set; }
public static Site Site { get; set; }
public static void Init()
{
//Get site info from DB here
//I need to inject _SiteRepository here but I can't
//since I don't have access to the constructor
}
}
I am new to IOC and I understand static classes are advised to be prevented. What is the good practice to handle this situation? I am thinking of converting this to a singleton but I am not sure if that is my best bet.

This is one of the reasons why I like to avoid static classes --they are hard to inject or invert control. They usually have to know intimate details of several low level classes. Since they are static classes you can leave them because they are already available to all of the other classes and don't require injection.
One trick that I've done is to create a second class that delegates into the static class. You can then put an interface onto the new class and get into an IoC framework easier.
public static class StaticClass
{
public static object Method()
}
public class NonstaticClass : INewInterface
{
public object Method()
{
return StaticClass.Method();
}
}
The good part of this refactor is that you can go method by method and then determine new objects and interfaces as you go. Eventually you may be able to get rid of the original static class. You would also register the new classes as singleton instances so that only one instance exists at a time.

In the context of an IoC container, it's a bit ambiguous to say 'convert it to a singleton'. If you mean the singleton design pattern, you probably shouldn't do it that way, as there are better alternatives in the IoC world.
IoC containers perform two main roles: to resolve dependencies between components, and to manage the lifetime of components. A container manages the lifetime of its components by deciding when to create and destroy component instances.
For example, when you call container.Resolve<SiteInfo>(), the container has to decide whether to re-use an existing SiteInfo instance or create a new one. How does the container decide? Well, when you register SiteInfo with the container, you can tell the container how you would like it to behave. If you register it as a Singleton, the container will only create a SiteInfo instance on the first call to container.Resolve<SiteInfo>(); on subsequent calls, it re-uses the existing SiteInfo instance.
The advantage of this technique over the singleton pattern is flexibility. If you use the design pattern, your SiteInfo class will forever be a singleton (unless you refactor). By using the container to manage the lifetime, you can change your mind later and just change the container registration code. Consumers of the component don't need to (and shouldn't) care whether the container provides them with a new instance or re-uses an existing one - they just call container.Resolve().
I'm not familiar with Windsor (I use Autofac), but it looks like you have two ways of registering a component as a singleton (I'm sure someone will correct me if this is wrong):
container.AddComponentLifeStyle<SiteInfo>(LifestyleType.Singleton)
or,
container.Register( Component.For<SiteInfo>()
.LifeStyle.Singleton );
However, a word of warning. In your example, your SiteInfo class has a dependency on the _SiteRepository class. You will therefore also need to register a _SiteRepository instance as a singleton in the container, so that it is available when the container resolves the SiteInfo. This _SiteRepository instance will remain in memory for the lifetime of the container, i.e. for the lifetime of the Web application, because it's a singleton. If the repository keeps a DB connection open, therefore, that connection will remain open for the same lifetime.
For this sort of reason, an alternative lifestyle is per-web-request - in other words, the container will create a new instance of your SiteInfo class once per web request. The per-web-request lifestyle is discussed in another question.

You can register an single instanec of a class in your container, so it behaves like a singleton. The container gives you the same instance every time.

Related

IoC container and dll memory management

I'm working on a server project and the server has a few different, independent layers and a few singleton classes. And I use the SimpleInjector, an IoC container, all across the layers. The full, executable example source code is available at https://github.com/DamonJung/TestAdvanture001.. ( It's unnecessarily lengthy because I was trying to reproduce a different problem there. )
I access the Singleton from Main method directly and indirectly from the IoC container.
// Use case in Main
.
.
using Impl;
static void Main(string args[])
{
.
.
// Singleton.Instance address = 0x0301f001 for example.
var context = Singleton.Instance.GetContext();
// SimpleInjector
// Singleton.Instance address inside of the dependency = 0x0408f023 for example.
var di = Container.GetInstance<ISomeInterface>();
var contextFromIoC = di.GetContext();
.
.
}
I expected the Singleton should be instantiated only once and the static instance should have the exact same memory address in the application, no matter where it's being invoked from and no matter how it's constructed ( by Main or the IoC container )
However, as the console output is saying, it didn't work that way. The Singleton's Instance shouldn't have been instantiated more than once. But they ended up having a different address on their own.
If my shallow understanding serves me right, the executable loads the dll into its own memory, and once the static member is created, the variable can be accessed throughout the AppDomain region.
Isn't this confirming the fact about static variables, isn't it?
Static Members
A non-static class can contain static methods, fields, properties, or events. The static member is callable on a class even when no instance of the class has been created. The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created. Static methods and properties cannot access non-static fields and events in their containing type, and they cannot access an instance variable of any object unless it is explicitly passed in a method parameter.
I was in search for the relevant read in SimpleInjector's documentation and found none. Reading about dynamic linking library and its memory management doesn't come right at me ( I shall be reading it further and over and over again anyway ! )
How a program treats dlls in terms of memory management
If IoC container is the scene behind, how SimpleInjector treats the dependencies when they are registered via Container.Register();
Above items would be my ultimate questions.
Two instances are created because your code creates two instances.
The first one is created by the following code
public class Singleton
{
public static readonly Singleton Instance = new Singleton();
// ....
}
and the second one is created when you register your type to SimpleInjector
If you want an instance to be created only once you could use a private constructor
public class Singleton
{
static Singleton()
{
Singleton.Instance = new Singleton();
}
public static Singleton Instance { get; }
private Singleton(){
}
}
This way only the Singleton class create itself.
To register your singleton in SimpleInjector you can use the RegisterInstance method :
container.RegisterInstance<Singleton>(Singleton.Instance);
By the way it is more common to let the container manage instances by itself and not rely on static property which could indicate that you are using a service locator which is a common anti pattern.
If you want to let SimpleInjector manage the instance you should use
container.RegisterSingleton<Singleton>();
This way SimpleInjector will create only one Singleton instance for the container.
See Singleton lifestyle in the SimpleInjector documentation

SimpleInjector ctor injection mix registered types and simple values

How do I register types which take another registered type as a parameter and also simple types (like an integer)?
public interface IDeviceManager
{
// implementation omitted.
}
public class DeviceManager : IDeviceManager
{
public DeviceManager(IDeviceConfigRepository configRepo, int cacheTimeout)
{
// implementation omitted
}
}
I do have a container registration for the IDeviceConfigRepository. That's ok. But how do I create an instance of DeviceManager with the configured dependency and passing along an integer of my choice in composition root?
I thought about creating a factory.
public class DeviceManagerFactory : IDeviceManagerFactory
{
private readonly Container _container;
public DeviceManagerFactory(Container container)
{
_container = container;
}
public DeviceManager Create(int minutes)
{
var configRepo = _container.GetInstance<IDeviceConfigurationRepository>();
return new DeviceManager(configRepo, minutes);
}
}
This is pretty simple.
However now I do not have a registration for DeviceManager which is the type I ultimately need. Should I change these dependencies to the factory instead?
public class ExampleClassUsingDeviceManager
{
private readonly DeviceManager _deviceManager;
public ExampleClassUsingDeviceManager(DeviceManager deviceManager, ...)
{
_deviceManage = deviceManager;
}
// actions...
}
For this to work and to avoid circular dependencies I would probably have to move the factory from the "application" project (as opposed to class libraries) where the composition root is to the project where the DeviceManager is implemented.
Is that OK? It would of course mean passing around the container.
Any other solutions to this?
EDIT
In the same project for other types I am using parameter objects to inject configuration into my object graph. This works OK since I only have one class instance per parameter object type. If I had to inject different parameter object instances (for example MongoDbRepositoryOptions) into different class instances (for example MongoDbRepository) I would have to use some kind of named registration - which SimpleInjector doesn't support. Even though I only have one integer the parameter object pattern would solve my problem. But I'm not too happy about this pattern knowing it will break as soon as I have multiple instances of the consuming class (i.e. MongoDbRepository).
Example:
MongoDbRepositoryOptions options = new MongoDbRepositoryOptions();
MongoDbRepositoryOptions.CollectionName = "config";
MongoDbRepositoryOptions.ConnectionString = "mongodb://localhost:27017";
MongoDbRepositoryOptions.DatabaseName = "dev";
container.RegisterSingleton<MongoDbRepositoryOptions>(options);
container.RegisterSingleton<IDeviceConfigurationRepository, MongoDbRepository>();
I am excited to hear how you deal best with configurations done at composition root.
Letting your DeviceManagerFactory depend on Container is okay, as long as that factory implementation is part of your Composition Root.
Another option is to inject the IDeviceConfigRepository into the DeviceManagerFactory, this way you can construct a DeviceManager without the need to access the container:
public class DeviceManagerFactory : IDeviceManagerFactory {
private readonly IDeviceConfigurationRepository _repository;
public DeviceManagerFactory(IDeviceConfigurationRepository repository) {
_repository = repository;
}
public DeviceManager Create(int minutes) {
return new DeviceManager(_repository, minutes);
}
}
However now I do not have a registration for DeviceManager which is the type I ultimately need. Should I change these dependencies to the factory instead?
In general I would say that factories are usually the wrong abstraction, since they complicate the consumer instead of simplifying them. So you should typically depend on the service abstraction itself (instead of depending on a factory abstraction that can produces service abstraction implementations), or you should inject some sort of proxy or mediator that completely hides the existence of the service abstraction from point of view of the consumer.
#DavidL points at my blog post about runtime data. I'm unsure though whether the cacheTimeout is runtime data, although you seem to be using it as such, since you are passing it in into the Create method of the factory. But we're missing some context here, to determine what's going on. My blog post still stands though, if it is runtime data, it's an anti-pattern and in that case you should
pass runtime data through method calls of the API
or
retrieve runtime data from specific abstractions that allow resolving runtime data.
UPDATE
In case the value you are using is an application constant, that is read through the configuration file, and doesn't change during lifetime of the application, it is perfectly fine to inject it through the constructor. In that case it is not a runtime value. There is also no need for a factory.
There are multiple ways to register this in Simple Injector, for instance you can use a delegate to register the DeviceManager class:
container.Register<DeviceManager>(() => new DeviceManager(
container.GetInstance<IDeviceConfigRepository>(),
cacheTimeout: 15));
Downside of this approach is that you lose the ability of Simple Injector to auto-wire the type for you, and you disable Simple Injector's ability to verify, diagnose and visualize the object graph for you. Sometimes this is fine, while other times it is not.
The problem here is that Simple Injector blocks the registration of primitive types (because they cause ambiguity) while not presenting you with a clean way to make the registration. We are considering (finally) adding such feature in v4, but that doesn't really address your current needs.
Simple Injector doesn't easily allow you to specify a primitive dependency, while letting the container auto-wire the rest. Simple Injector's IDependencyInjectionBehavior abstraction allows you to override the default behavior (which is to disallow doing this). This is described here, but I usually advice against doing this, because it is usually requires quite a lot of code.
There are basically two options here:
Abstract the specific logic that deals with this caching out of the class and wrap it in a new class. This class will have just the cacheTimeout as its dependency. This is of course only useful when there actually is logical to abstract and is usually only logical when you are injecting that primitive value into multiple consumers. For instance, instead of injecting a connectionstring into multiple classes, you're probably better of injecting an IConnectionFactory into those classes instead.
Wrap the cacheTimeout value into a complex data container specific for the consuming class. This enables you to register that type, since it resolves the ambiguity issue. In fact, this is what you yourself are already suggesting and I think this is a really good thing to do. Since those values are constant at runtime, it is fine to register that DTO as singleton, but make sure to make it immutable. When you give each consumer its own data object, you won't have to register multiple instances of those, since they are unique. Btw, although named registations aren't supported, you can make conditional or contextual registrations using RegisterConditional and there are other ways to achieve named registrations with Simple Injector, but again, I don't think you really need that here.

Domain Driven Design - Singletons

It's a bad idea to create a singleton when we are using ddd?
I'm thinking of creating two of them, one for global settings (which are saved in the database) and the other for local settings (which are saved in the Windows Registry in my application windows forms).
If singletons in ddd is acceptable, where and when should I fill them with the stored values?
Singletons implemented as is (1) aren't acceptable in DDD based on your case(2) and even in any other modern software development paradigm. Note that DDD is more than a software architectural paradigm, but when I say that common singleton implementation isn't acceptable I'm talking about how to properly implement DDD in programming languages like C#.
For example, the following code sample is a possible simple implementation of singleton:
// Very simple singleton using a static field initializer
public class SimpleSingleton
{
private readonly static SimpleSingleton _instance = new SimpleSingleton();
public SimpleSingleton Instance => _instance;
}
They're not swappable, and this means that you can't inject them using dependency injection(3). That is, testing is harder to implement too (you should understand that a system that can't be tested or it's hard to test is a very bad idea).
What can be acceptable is using a dependency injection/inversion of control container that can define component implementations' life-style like Castle Windsor and others, which means that you can still use dependency injection and define that only a single instance will be created during the life of the application (i.e. you get an instance where you get an injected component implementation, but once one is created by the internal component factory, this is the one that's being injected during one application life-cycle).
At the end of the day, your system is designed to be agnostic about how component life-cycle works. It's defined by configuration. I would say that object life management is an aspect when your system is designed this way (see this Wikipedia article to learn more about aspect-oriented programming).
Delegating component life management to an aspect and define what kind of life will have your components is a great advantage: your code can work in many hosting environments and on each of them your code can work differently by configuration.
Think about an ASP.NET WebAPI. Maybe some components should be singletons during a single request, and each request should work with its own singleton. Same component used in another environment maybe shouldn't be a singleton, but just a transient object (i.e. each time you inject it, it's a completely new object). With common singleton implementations you won't get this flexibility.
Your requirement done right
There're many possible approaches to provide a good solution to your problem. I'll describe two of many possible solutions:
1. Instead of thinking about a global settings object, you should inject these settings as a class of settings into each component where you require these settings
For example:
public interface IDatabaseSettings
{
string Host { get; set; }
}
public class RegistryDatabaseSettings : IDatabaseSettings
{
// This property should get and set the setting from and
// against the Windows Registry. It's just a sample and dummy
// implementation
public string Host { get; set; }
}
public interface ISomeRepository
{
}
public class SomeRepositoryImpl : ISomeRepository
{
private readonly IDatabaseSettings _dbSettings;
// Inject IDatabaseSetttings as constructor's dependency
public SomeRepositoryImpl(IDatabaseSettings dbSettings)
{
_dbSettings = dbSettings;
}
public IDatabaseSettings DatabaseSettings => _dbSettings;
}
And using your favourite inversion of control/dependency injection container, you can define that IDatabaseSettings must be instantiated once per application cycle (i.e. singleton).
2. If settings are a cross-layer concern...
...maybe you can define a class called Settings where you define all settings as public properties and you inject a singleton instance into any component requiring it:
public interface IDatabaseSettings
{
string Host { get; set; }
}
public interface ISettings
{
IDatabaseSettings Database { get; }
}
public interface ISomeRepository
{
}
public class SomeRepositoryImpl : ISomeRepository
{
private readonly ISettings _settings;
// Inject Settings as constructor's dependency
public SomeRepositoryImpl(ISettings settings)
{
_settings = settings;
// Now you can access DatabaseSettings as follows:
// Settings.Database.Host
}
public ISettings Settings => _settings;
}
For me, the issue with this approach is you're going to inject settings to components that shouldn't access/write settings which are from other domains or they're just not desirable to be accessed everywhere. I'm talking about not breaking one of most important principles in object-oriented programming: encapsulation.
(1) When I talk about a singleton pattern implementation as is, I'm describing a common singleton pattern implementation where the whole singleton class implements the single object life instantiation/management.
(2) OP talks about a settings that should be stored in some database and in Windows Registry. It would be a bad idea not using dependency injection, because there would be no chance to unit test a component requiring the whole settings without also involving the database and Windows Registry. Setting fakes wouldn't be possible.
(3) Some inversion of control containers have support to configure components using custom factories, where you can define that an instance of some implementation can be taken from any custom source. For example, that factory can return SomeSingleton.Instance and get it injected as any regular component.

Limited singleton lifetime determined by another object

This may be something to be solved with Autofac nested scopes, but I have not been able to make enough of the documentation to figure it out myself.
I think what I am looking for is like a per-HTTP-request singleton, but the place of the request is taken by the lifetime of another object.
There is a class SubSystem, of which a new instance is created (resolved from the container, potentially through a factory class) every time new data is loaded into the application (the old data and SubSystem instance are discarded).
Then there are classes SomeFeature, implementing IFeature, and SomeService, implementing ISomeService.
SubSystem has dependencies on both IFeature and IService, while SomeFeature takes a dependency on IService. So the object graph looks like this:
SubSystem
└> SomeService : IService <─┐
└> SomeFeature : IFeature ├─── same instance
└> SomeService : IService <─┘
IFeature is only required in one place, so a transient registration is fine here. IService on the other hand must be resolved to the same instance for all dependencies within this subgraph, but when new data is loaded and a new SubSystem instance is created, its subgraph must get its own new "per-request singleton" IService instance.
The reason for discarding the instances is that they cache information from the loaded data for performance reasons, which will not be valid anymore when new data is loaded. I am currently using real singleton instances that have their local state reset via an event raised in the SubSystem constructor, but that is clearly a less than optimal solution.
As I said, I'd like this to work like InstancePerHttpRequest(), but as "instance per SubSystem".
Is there a way to achieve this using the Autofac API?
The option I think you're looking for is:
.InstancePerOwned<SubSystem>()
If you only consume SubSystem in one place, just take a dependency on Owned<SubSystem> at that point, and make sure you Dispose() the Owned<T> in the consuming component's Dispose() method.
For something a bit more transparent, assuming you can create ISubSystem to go with SubSystem you can do this:
builder.RegisterType<SubSystem>()
.InstancePerOwned<SubSystem>();
builder.RegisterType<SubSystemGraph>()
.As<ISubSystem>()
// Appropriate sharing here...
;
Where SubSystemGraph is:
class SubSystemGraph: ISubSystem, IDisposable
{
readonly Owned<SubSystem> _root;
public SubSystemGraph(Owned<SubSystem> root)
{
_root = root;
}
public void Dispose()
{
_root.Dispose();
}
// Methods of ISubSystem delegate to _root.Value
public void Foo()
{
_root.Value.Foo();
}
}
(This could be packaged up into a nicer interface on Autofac but it's not all that common in practice.)

Resolve type with IoC Container from within static Method

When using an IoC container without a static container instance (as this would result in a a service locator anti-pattern), how to resolve types from a static method?
Say, I have a method that reads an object Document from a file:
public class Document {
// when used with IoC, the Logger gets injected via property injection
public ILogger Logger { get; set; }
/* ... */
public static Document Read (string filePath)
{
// need to resolve an ILogger at this point?
Logger.Info ("reading in {0}", filePath);
/* ...read in document an return a document instance here ... */
}
}
The Code is C# but same problem would apply to a Java project.
I know that a simple answer would be "don't use static method", but given the method is stateless i think it is one of the cases where static methods make sense.
Having a singleton IoC container would also help, but this is widely known to be an anti-pattern.
So, what is the way out of the problem?
Although, I can understand why this makes sense to write this function as static, the answer is simply that DI is not going well with static methods that have an associated state. Injected properties are a state of the object and static methods that have an associated state are considered to be an anti-pattern.
DI sometimes forces you to use pure (not anti) patterns.
If you insist on using static method in your case, I can suggest these to cover your options. All are not perfect.
Adding the injected objects as parameters to the function.
Document.Read(logger, filePath).
If you weren't using an IoC framework, the alternative was:
new Document(logger).Read(filepath)
which is more or less, the same clumsy code for the caller.
Using a ServiceLocator as you stated.
Add a static initialization method to the class, and inject all of it's dependencies (as static properties). You would have to call this initialization in your application start.

Categories

Resources