I am working on an MEF project to discover usage and implementation techniques. My first phase of discovery is to implement a dynamically configurable and centralized data controller. One way to customize behavior is to inherit a class I provide that enforces a singularity rule. While the Singleton pattern is much maligned in it's use, I may have found an implementation that could validate, to some degree, the pattern's struggling existence.
The Situation
Suppose a data control module (DataController) imported by the Host is intended to supply a common conduit to databases on request by sibling modules. I only need one DataController and to be composed as a module, DataController must implement IDataController. Implementation of DataProvider as the base class is purely optional; however, derivation from DataProvider will require some additional handling.
The Observations
Gathering the facts:
A static class cannot implement or
extend abstract classes or
interfaces. This fact alone
eliminates the use of a static class
to ensure a singular existence of a
DataController.
A DataController implementing the
Singleton pattern would ensure a
singular existence per application
domain. There is no restriction on
the DataController; allowed to inherit the
required interface to be imported and
composed in the Host.
Given derivation of DataController, the
standard implementation for the
Singleton pattern may prove to be
challenging in same cases. The
proposed data library provides both
publicly accessible classes:
IDataController, and an abstract
DataProvider. To ensure a single
instance of the derived DataController,
the implementation will require some
deviation from the norm.
The Solution
At this point, the solution seems clear. Implementation of the Singleton pattern by the DataHandler base class. I am not naive enough to think that there are other ways I could do this. But here is my rough expectations on how to implement the pattern:
// DataLibrary referenced by Host
public interface IDataController
{
IDataController Start();
DbConnection CreateConnection<TDbConnection>(params string[] args)
where TDbConnection : DbConnection, IDbConnection;
}
public abstract class DataProvider
{
// singleton implementation
private static IDataController dcInstance;
protected static IDataController Instance
{
get{ return dcInstance; }
}
// ========================
abstract IDataController CreateController();
protected IDataController instanceController<TDataController>()
where TDataController : IDataController, new()
{
return new TDataController ();
}
}
// references DataLibrary
[Export(typeof(IDataController))]
public class DataController : DataProvider, IDataController
{
public IDataController Start()
{
return CreateController();
}
protected override IDataController CreateController()
{
return instanceController<DataController>();
}
public SqlConnection CreateConnection(params string[] args)
{
// instance and return new SqlConnection
}
}
Keep in mind that I have been working this out - read, theorizing - and have not completed the implementation. There will most likely be some updates as I debug any issues.
Obviously, this implementation is only enforced if the DataController module inherits the abstract base class, DataProvider. Therefore, it stands to reason that we should enforce a rule of singularity to avoid abuse or misuse if the developer opts to derive a DataController from DataProvider.
All that said, I am curious if there is a more acceptable, or practical implementation than what I have devised. And, I begin to question if the Singleton pattern is the right choice. With the Singleton pattern's much maligned existence (and, for the most part, rightfully so), I should, therefore, question my choice.
Is there a more practical implementation to meet my requirements?
*Is this the right implementation of the Singleton pattern in this case?*
Does this implementation actually lend any value to the pattern's existence?
If you want to enforce the fact that only a single instance of a class exists in the container, then you can just set the "shared" part creation policy:
[Export(typeof(IDataController))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class DataController : IDataController
{
...
}
Each part importing IDataController will then receive the same instance. Note that this already the default behavior in MEF if you specify no part creation policy at the import or export side.
You should not build "singletonness" into a class. Whether something is a singleton is part of the component metadata or the configuration of the container. Other dependency injection containers follow the same approach. For example, in autofac you declare something as being a singleton like this:
builder.Register(c => new DataController())
.As<IDataController>().SingleInstance();
Unless you have more implementation code that all derived classes from DataProvider would share, you might want to simply do away with your abstract class. This implementation guarantees thread-safey and uses lazy construction without the use of locks. However, requires .NET 4.
public interface IDataController
{
DbConnection CreateConnection<TDbConnection>(params string[] args)
where TDbConnection : DbConnection, IDbConnection;
}
[Export(typeof(IDataController))]
public class DataController : IDataController
{
// singleton implementation
private static volatile Lazy<IDataController> _ControllerInstance = new Lazy<IDataController>(() => new DataController());
public static IDataController ControllerInstance
{
get { return _ControllerInstance.Value; }
}
public DbConnection CreateConnection<TDbConnection>(params string[] args)
where TDbConnection : DbConnection, IDbConnection
{
throw new NotImplementedException();
}
}
Related
In my project I have more than one database contexts, so I have created a provider for getting the context objects based on need.
My provider is looks like this.
public class DbContextProvider
{
public Func<AccountingContext> AccountingDbContextResolver { get; set; }
public Func<ActiveDirectryContext> ActiveDirectryDbContextResolver { get; set; }
public AccountingContext GetAccountingDbContext() =>
this.AccountingDbContextResolver();
public ActiveDirectryContext GetActiveDirectryDbContext() =>
this.ActiveDirectryDbContextResolver();
}
One ServiceBase class I have created for getting the provider
public class ServiceBase
{
public ServiceBase(DbContextProvider contextProvider)
{
this.ContextProvider = contextProvider;
}
protected DbContextProvider ContextProvider { get; }
public AccountingContext AccountingDbContext =>
this.ContextProvider.GetAccountingDbContext();
public ActiveDirectryContext ActiveDirectryDbContext =>
this.ContextProvider.GetActiveDirectryDbContext();
}
I am using simple injector and I need to create instance of both Database contexts.
For getting the instance I have created two static methods with delegate
private static DbContextProvider CreateActiveDirectryDbContextProvider(Container container)
{
return new DbContextProvider
{
ActiveDirectryDbContextResolver =
() => container.GetInstance<ActiveDirectryContext>();
};
}
private static DbContextProvider CreateAccountingDbContextProvider(Container container)
{
return new DbContextProvider
{
AccountingDbContextResolver = () => container.GetInstance<AccountingContext>();
};
}
And for registrations I have used the below code
var accountingProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(accountingProvider);
var activeDirectryProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(activeDirectryProvider);
If i run the code then I am getting an error like below
System.InvalidOperationException: 'Type DbContextProvider has
already been registered. If your intention is to resolve a collection
of DbContextProvider implementations, use the
Container.Collection.Register overloads. For more information, see
https://simpleinjector.org/coll1. If your intention is to replace the
existing registration with this new registration, you can allow
overriding the current registration by setting
Container.Options.AllowOverridingRegistrations to true. For more
information, see https://simpleinjector.org/ovrrd.'
But everything is working fine when I try with only one context that is ,
var accountingProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(accountingProvider);
I have tried to register it using container.Collection.Register, no error is coming but I am not getting the instance in the service layer , I am getting a null reference exception there.
can someone help me to resolve this ?
You only have one type (DbContextProvider) that is responsible for constructing both AccountingContext and ActiveDirectryContext. From that perspective, it is really strange to create two DbContextProvider instances that are each partly initialized. A consumer would not expect GetAccountingDbContext() to return null or throw a NullReferenceException. So instead, you should create one single instance that can be used for both cases:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
container.RegisterInstance<DbContextProvider>(new DbContextProvider
{
ActiveDirectryDbContextResolver = () => container.GetInstance<ActiveDirectryContext>(),
AccountingDbContextResolver = () => container.GetInstance<AccountingContext>()
});
Or better, make DbContextProvider immutable:
container.RegisterInstance<DbContextProvider>(new DbContextProvider(
activeDirectryDbContextResolver: () => container.GetInstance<ActiveDirectryContext>(),
accountingDbContextResolver: () => container.GetInstance<AccountingContext>()));
This fixes the problem, because there is no only one registration for DbContextProvider. This removes the ambiguity, prevents possible bugs, and is a simpler solution.
But while this would work, I would like to suggest a few changes to your design.
Composition over Inheritance
First of all, you should get rid of the ServiceBase base class. Although base classes are not bad per see, when they start to get dependencies of their own, they likely start to violate the Single Responsibility Principle, and their derivatives the Dependency Inversion Principle and the Open/Closed Principle:
Base classes with dependencies often become a hodgepodge of functionality—often cross-cutting concerns. The base class becomes an ever-growing class. Ever-growing classes are an indication of a Single Responsibility Principle violation.
When the base class starts to contain logic, the derivatives automatically depend on that behavior—A derivative is always strongly coupled to its base class. This makes it hard to test the derivative in isolation. In case you ever want to replace or mock the behavior of the base class, it means that its behavior is Volatile. When a class is tightly coupled with a Volatile Dependency, it means you are violating the Dependency Inversion Principle.
The base class's constructor dependencies need to be supplied by the derived class's constructor. This will cause sweeping changes when the base class requires a new dependency, because all derived constructors need to be updated as well.
Instead, of using base classes, do the following:
Instead of forwarding dependencies from the derived class to the base class constructor, the derived class should store the dependency itself in a private field. It can use that dependency directly.
In case the base class contains behavior besides code:
In case that behavior is Volatile, wrap the logic in a class, hide that class behind an abstraction and inject the class (through its abstraction) into the constructor of the derived class. When doing this, it becomes very easy to see what dependencies the derived class has.
In case the behavior is Stable, you can use static helper classes or extension methods to make the base class's behavior reusable.
In case the behavior concerns a cross-cutting concern, consider the use of Decorators or Dynamic Interception as an alternative to base classes.
When you follow this advice, what you end up with is a set of (derived) service classes that depend on a base class that is nothing more than an empty shell. This is when you can remove the base class altogether. What you now achieved is Composition over Inheritance. Composition typically leads to more maintainable systems than inheritance does.
Closure Composition Model
As JoostK mentioned, you can also inject the DbContext types directly into consumers. Whether or not you want to do this, however, depends on the type of composition model you decided to use. What this means is that, when you choose to apply the Closure Composition Model, you should typically inject the DbContext implementations directly into your consumers.
public class ProduceIncomeTaxService : IHandler<ProduceIncomeTax>
{
private readonly AccountingContext context;
// Inject stateful AccountingContext directly into constructor
public ProduceIncomeTaxService(AccountingContext context) => this.context = context;
public void Handle(ProduceIncomeTax command)
{
var record = this.context.AccountingRecords
.Single(r => r.Id == command.Id);
var tax = CalculateIncomeTax(record);
FaxIncomeTax(tax);
this.context.SaveChanges();
}
...
}
This simplifies the registrations of your system, because now you just register the DbContext implementaions and you're done:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
// Of course don't forget to register your service classes.
Interface Segregation Principle
Your current DbContextProvider seems to designed around the Ambient Composition Model. There are advantages of both composition models, and you might have chosen deliberately for the Ambient Composition Model.
Still, however, the DbContextProvider exposes many (10) properties—one for each DbContext. Classes and abstractions with many methods can cause a number of problems concerning maintainability. This stems from the Interface Segregation Principle that prescribes narrow abstractions. So instead of injecting one wide provider implementation that gives access to a single DbContext type. Implementations would typically only require access to a single DbContext type. If they require multiple, the class should almost certainly be split up into smaller, more-focused classes.
So what you can do instead is create a generic abstraction that allows access to a single DbContext type:
public interface IDbContextProvider<T> where T : DbContext
{
T Context { get; }
}
When used in a consumer, this would look as follows:
public class ProduceIncomeTaxService : IHandler<ProduceIncomeTax>
{
private readonly IDbContextProvider<AccountingContext> provider;
// Inject an ambient context provider into the constructor
public ProduceIncomeTaxService(IDbContextProvider<AccountingContext> provider)
=> this.provider = provider;
public void Handle(ProduceIncomeTax command)
{
var record = this.provider.Context.AccountingRecords
.Single(r => r.Id == command.Id);
var tax = CalculateIncomeTax(record);
FaxIncomeTax(tax);
this.provider.Context.SaveChanges();
}
...
}
There are multiple ways to implement IDbContextProvider<T>, but you can, for instance, create an implementation that directly depends on Simple Injector:
public sealed class SimpleInjectorDbContextProvider<T> : IDbContextProvider<T>
where T : DbContext
{
private readonly InstanceProducer producer;
public SimpleInjectorDbContextProvider(Container container)
{
this.producer = container.GetCurrentRegistrations()
.FirstOrDefault(r => r.ServiceType == typeof(T))
?? throw new InvalidOperationException(
$"You forgot to register {typeof(T).Name}. Please call: " +
$"container.Register<{typeof(T).Name}>(Lifestyle.Scope);");
}
public T Context => (T)this.producer.GetInstance();
}
This class uses the injected Container to pull the right InstanceProducer registration for the given DbContext type. If this is not registered, it throws an exception. The InstanceProducer is then used to get the DbContext when Context is called.
Since this class depends on Simple Injector, it should be part of your Composition Root.
You can register it as follows:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
container.Register(
typeof(IDbContextProvider<>),
typeof(SimpleInjectorDbContextProvider<>),
Lifestyle.Singleton);
I am implementing IServiceLocator(CommonServiceLocator package) into my custom ServiceLocator class.
The interface has the following methods to implement:
public class CustomServiceLocator : IServiceLocator
{
private IServiceProvider _provider;
public RatioDissectionServiceLocator(IServiceProvider provider)
{
_provider = provider;
}
public IEnumerable<object> GetAllInstances(Type serviceType)
{
throw new NotImplementedException();
}
public IEnumerable<TService> GetAllInstances<TService>()
{
throw new NotImplementedException();
}
public object GetInstance(Type serviceType)
{
throw new NotImplementedException();
}
public object GetInstance(Type serviceType, string key)
{
throw new NotImplementedException();
}
public TService GetInstance<TService>()
{
return _provider.GetService<TService>();
}
}
I don't want to implement all the methods in my class. How can we achieve ISP for inbuilt C# interfaces?
Any help?
The Interface Segregation Principle states:
No client should be forced to depend on methods it does not use.
What this means is that despite many unclear and misleading explanations of the principle, a big interface by itself doesn't violate the principle. Perhaps another class actually does depend on all the members of the interface. So we wouldn't look at an interface like IServiceLocator and try to "fix" it somehow.
The ISP is from the point of view of classes that depend on interfaces. If an interface has 20 members and my class depends on all of them, it's not an ISP violation. (It's likely all sorts of other bad things that have nothing to do with the ISP.) If another class depends on the exact same interface and uses only a few members, that's an ISP violation.
In both examples it's the same interface. The principle isn't about the interface. It's about whether or not a class that depends on the interface uses all of its members.
(Another weird example I see a lot is a big interface and a class that implements the interface but throws NotImplementedException for some members. That's also bad, and it's a Liskov Substitution violation, but it has nothing at all to do with ISP. Implementing an interface is not depending on it.)
One way to avoid ISP violations is to write interfaces from the perspective of classes that depend on them. Whatever your class needs from its dependency, write your interface to describe exactly that. If the concrete inner implementation is a framework class with 100 members, wrap it in your own class:
public interface ISmallSegregatedInterface
{
void DoJustWhatMyClassNeeds();
}
public class TheImplementation : ISmallSegregatedInterface
{
private readonly FrameworkClassWithLotsOfMembers _inner;
public TheImplementation(FrameworkClassWithLotsOfMembers inner)
{
_inner = inner;
}
public void DoJustWhatMyClassNeeds()
{
_inner.CallSomeMethod();
}
}
Now the class that needs to depend on one method can depend on an interface with just that one method. (Over time I've found that this leads to lots of single-method interfaces. I think that logically leads to depending on functions and delegates but a single-method interface is okay.
That is interface segregation. Your classes don't depend on a big interface they don't need. They depend on one ore more interfaces that describe exactly what they need. This is often accomplished by creating the interface from the perspective of the class that needs to depend on it.
What you might find is that no class needs to depend on all of the methods of IServiceLocator.
Maybe all you need is this:
TService GetInstance<TService>();
But does a class really need to depend on a method that can return anything? In other words, you're probably only going to request one or two dependencies. So maybe what you really need is this:
public interface ISomethingSpecificFactory
{
ISomethingSpecific CreateInstance();
}
Or you might find that you don't need the factory at all - perhaps you can just inject ISomethingSpecific instead of a factory that creates an instance of ISomethingSpecific.
Another way of looking at it: If you don't need to implement all of the methods of IServiceLocator then you don't need to create a class that implements IServiceLocator.
IServiceLocator is a framework interface. Unlike most software we create, it doesn't exist to meet a narrow, specific need. It meets a broader variety of needs that are determined as we write our software. That's why it makes more sense that it has all sorts of varied methods we might not need.
One reason for the ISP is that if lots of classes depend on different members of an interface, we might be pressured to change the interface because of the needs of one client, and those changes affect other clients that depend on other methods, in effect coupling them all together.
We can't change IServiceLocator so that pressure doesn't exist. So technically, even if we did violate the ISP by depending on that interface, it wouldn't have the harmful effect that the ISP protects us from.
if I have a interface like below,
public interface IMethods
{
void M1();
void M2();
}
then I want to create a singleton class by inheriting above interface, then what's the benefit in context of re use of singleton class and how?
The singleton aspect is just one implementation of the IMethods contract, giving you the benefit of the singleton pattern, assuming that is what you need.
The benefit of exposing that singleton through an interface is that the consumer doesn't need to care how it is implemented, just that it is implemented and they can use it. At a later date if you suddenly need a regular instance as opposed to a singleton, you can change that without impacting consumers.
This happens very frequently with DI containers, where you can usually configure the lifecycle of a binding to be in singleton scope.
If you use the singleton directly and never really use the interface, then there is little use in the interface. If the singleton is being used without really needing to constrain it to a single instance, then there is little use in adopting the singleton pattern.
I'm not entirely sure what you're asking, but if you're asking "what's the benefit of implementing this interface as a singleton" the answer is the same benefit that singleton always offers: "a guarantee of one instance no matter how many places it's used". Singleton exists to enforce a single instance of a class with instance access vs static class and methods/properties. An example implementation:
public class Methods : IMethods
{
// Singleton instance
private static readonly IMethods _instance = new Methods();
// Private constructor to enforce singleton
private Methods()
{
}
// The instance getter
public static IMethods Instance
{
get
{
return _instance;
}
}
public void M1()
{
}
public void M2()
{
}
}
The thing that will hose you here is the fact that the Instance property is not exposed on the IMethods interface, so getting it requires the instance type to be Methods and not IMethods which sort of defeats the purpose of the inheriting the interface.
Often, people use dependency injection frameworks to set the lifetime of an interface's implementation to singleton AKA shared instance instead. It is more "OO friendly".
I've been guilty of having a 1-to-1 relationship between my interfaces and concrete classes when using dependency injection. When I need to add a method to an interface, I end up breaking all the classes that implement the interface.
This is a simple example, but let's assume that I need to inject an ILogger into one of my classes.
public interface ILogger
{
void Info(string message);
}
public class Logger : ILogger
{
public void Info(string message) { }
}
Having a 1-to-1 relationship like this feels like a code smell. Since I only have a single implementation, are there any potentially issues if I create a class and mark the Info method as virtual to override in my tests instead of having to create an interface just for a single class?
public class Logger
{
public virtual void Info(string message)
{
// Log to file
}
}
If I needed another implementation, I can override the Info method:
public class SqlLogger : Logger
{
public override void Info(string message)
{
// Log to SQL
}
}
If each of these classes have specific properties or methods that would create a leaky abstraction, I could extract out a base class:
public class Logger
{
public virtual void Info(string message)
{
throw new NotImplementedException();
}
}
public class SqlLogger : Logger
{
public override void Info(string message) { }
}
public class FileLogger : Logger
{
public override void Info(string message) { }
}
The reason why I didn't mark the base class as abstract is because if I ever wanted to add another method, I wouldn't break existing implementations. For example, if my FileLogger needed a Debug method, I can update the base class Logger without breaking the existing SqlLogger.
public class Logger
{
public virtual void Info(string message)
{
throw new NotImplementedException();
}
public virtual void Debug(string message)
{
throw new NotImplementedException();
}
}
public class SqlLogger : Logger
{
public override void Info(string message) { }
}
public class FileLogger : Logger
{
public override void Info(string message) { }
public override void Debug(string message) { }
}
Again, this is a simple example, but when I should I prefer an interface?
The "Quick" Answer
I would stick with interfaces. They are designed to be contracts for consumption for external entities.
#JakubKonecki mentioned multiple inheritance. I think this is the biggest reason to stick with interfaces as it will become very apparent on the consumer side if you force them to take a base class... no one likes base classes being thrust upon them.
The Updated "Quick" Answer
You have stated issues with interface implementations outside your control. A good approach is to simply create a new interface inheriting from the old one and fix your own implementation. You can then notify the other teams that a new interface is available. Over time, you can deprecate older interfaces.
Don't forget you can use the support of explicit interface implementations to help maintain a nice divide between interfaces that are logically the same, but of different versions.
If you want all this to fit in with DI, then try not to define new interfaces and instead favour additions. Alternatively to limit client code changes, try to inherit new interfaces from old ones.
Implementation vs. Consumption
There is a difference between implementing the interface and consuming it. Adding a method breaks the implementation(s), but does not break the consumer.
Removing a method obviously breaks the consumer, but does not break the implementation - however you wouldn't do this if you are backwards-compatibility conscious for your consumers.
My Experiences
We frequently have a 1-to-1 relationship with interfaces. It is largely a formality but you occasionally get nice instances where interfaces are useful because we stub / mock test implementations, or we actually provide client-specific implementations. The fact that this frequently breaks that one implementation if we happen to change the interface isn't a code smell, in my opinion, it is simply how you work against interfaces.
Our interface-based approach is now standing us in good stead as we utilise techniques such as the factory pattern and elements of DI to improve an aged legacy code base. Testing was able to quickly take advantage of the fact that interfaces existed in the code base for many years before finding a "definitive" use (ie, not just 1-1 mappings with concrete classes).
Base Class Cons
Base classes are for sharing implementation details to common entities, the fact they are able to do something similar with sharing an API publicly is a by-product in my opinion. Interfaces are designed to share API publicly, so use them.
With base classes you could also potentially get leakage of implementation details, for example if you need to make something public for another part of the implementation to use. These are no conducive to maintaining a clean public API.
Breaking / Supporting Implementations
If you go down the interface route you may run into difficulty changing even the interface due to breaking contracts. Also, as you mention, you could break implementations outside of your control. There are two ways to tackle this problem:
State that you won't break consumers, but you won't support implementations.
State that once an interface is published, it is never changed.
I have witnessed the latter, I see it come in two guises:
Completely separate interfaces for any new stuff: MyInterfaceV1, MyInterfaceV2.
Interface inheritance: MyInterfaceV2 : MyInterfaceV1.
I personally wouldn't choose to go down this route, I would choose to not support implementations from breaking changes. But sometimes we don't have this choice.
Some Code
public interface IGetNames
{
List<string> GetNames();
}
// One option is to redefine the entire interface and use
// explicit interface implementations in your concrete classes.
public interface IGetMoreNames
{
List<string> GetNames();
List<string> GetMoreNames();
}
// Another option is to inherit.
public interface IGetMoreNames : IGetNames
{
List<string> GetMoreNames();
}
// A final option is to only define new stuff.
public interface IGetMoreNames
{
List<string> GetMoreNames();
}
Your ILogger interface is breaking the interface segregation principle when you start adding Debug, Error, and Critical methods besides Info. Take a look at the horrible Log4Net ILog interface and you'll know what I'm talking about.
Instead of creating a method per log severity, create a single method that takes a log object:
void Log(LogEntry entry);
This completely solves all of your problems, because:
LogEntry will be a simple DTO and you can add new properties to it, without breaking any client.
You can create a set of extension methods for your ILogger interface that map to that single Log method.
Here's an example of such extension method:
public static class LoggerExtensions
{
public static void Debug(this ILogger logger, string message)
{
logger.Log(new LogEntry(message)
{
Severity = LoggingSeverity.Debug,
});
}
public static void Info(this ILogger logger, string message)
{
logger.Log(new LogEntry(message)
{
Severity = LoggingSeverity.Information,
});
}
}
For a more detailed discussion on this design, please read this.
You should always prefer the interface.
Yes, in some cases you will have the same methods on class and interface, but in more complex scenarios you won't. Also remember, that there is no multiple inheritance in .NET.
You should keep your interfaces in a separate assembly and your classes should be internal.
Another benefit of coding against interfaces is an ability to easily mock them in unit tests.
I Prefer interfaces. Given stubs and mocks are also implementations (sort of), I always have at least two implementations of any interface. Also, Interfaces can be stubbed and mocked for tests.
Further, the contract angle that Adam Houldsworth mentions is very constructive. IMHO it makes the code cleaner than 1-1 implementations of interfaces make it smelly.
I am looking to see how Ioc/Di can simplify wiring the following classes I use often.
Consider a library that has an abstract notion of an Entity and an interface for a data access object:
public abstract class EntityWithTypedId<TId> : IEntityWithTypedId<TId>{...}
public interface IDao<T, TId> where T : IEntityWithTypedId<TId>
For the dao, I have one implementation for NHibernate as well as a fake dao I find useful for testing:
// has an NHib implementation
public class Dao<T, TId> : IDao<T, TId> where T : EntityWithTypedId<TId> {...}
public class DaoFakeBase<T> : IDao<T, int>, IDisposable where T : IEntityWithTypedId<int> {...}
I currently do the following to define an Entity and Dao type for a given project:
/// <summary>
/// <see cref="IEntityWithTypedId{IdT}"/> with an int for an id
/// </summary>
[Serializable]
public abstract class Entity : EntityWithTypedId<int>
{
}
public class Dao<T> : Dao<T, int> where T : Entity
{
protected Dao(ISessionFactory sessionFactory) : base(sessionFactory) { }
}
Can I use a DI tool to define the Entity instead? Can someone show me a code sample of how to do it if so?
Can you also lay out how I might tell my test assembly to use DaoFakes and production to use NHib.Dao
I have been looking at Windsor, mostly because NHibernate contrib projects use it, but am also interested in MEF, AutoFac and Ninject, in that order. I realize that MEF is not an IoC container in the sense that Windsor is. From what I can see with Windsor I would use Installer classes, maybe an EntityInstaller and a DaoInstaller, although I might be missing a FActory type of object here too.
Cheers,
Berryl
UPDATE # KeithS
Are you saying to change something like:
class MyViewModel(IDao<MyClass, int> dao) {...}
becomes something like
class MyViewModel(Func<IDao<MyClass, int>, obj> getDaoFunc) {
_dao = getDaoFunc(this);
}
In your example...
class MyViewModel(IDao<MyClass, int> dao) {...}
...IDao would get resolved at runtime based on a previous registration within your container. The syntax for a Prism/Unity implementation is below...
IUnityContainer.RegisterType<IDao..., DaoFakeBase...>();
The RegisterType takes place within IModule.Initialize() of a given module as defined in the UnityBootstrapper class.
protected override IModuleCatalog GetModuleCatalog()
{
ModuleCatalog catalog = new ModuleCatalog();
catalog.AddModule(typeof(project.Init));
return catalog;
}
You can also register a given type based on a lifetime manager; to behave as a Singleton...
IUnityContainer.RegisterType<IShellController, ShellController>(new ContainerControlledLifetimeManager());
...where the IShellController resolved instance will remain the same returned instance throughout the lifetime of the IUnityContainer.
UPDATE:
Using your code the registration would look like this...
public interface IDao<T, TId> where T : IEntityWithTypedId<TId>
{ }
public class Dao<T, TId> : IDao<T, TId> where T : EntityWithTypedId<TId>
{ }
public class TId
{ }
public abstract class EntityWithTypedId<TId> : IEntityWithTypedId<TId>
{ }
public interface IEntityWithTypedId<TId>
{ }
IUnityContainer.RegisterType<IEntityWithTypedId<TId>, EntityWithTypedId<TId>>();
IUnityContainer.RegisterType<IDao<IEntityWithTypedId<TId>, TId>, Dao<IEntityWithTypedId<TId>, TId>>();
IDao<IEntityWithTypedId<TId>, TId> dao = IUnityContainer.Resolve<IDao<IEntityWithTypedId<TId>, TId>>();
I would not use IoC to register the relationship between DAOs and their types (which is basically what you'd be doing). This will lead to you using the IoC container as a "service locator", a known anti-pattern where you pass the IoC container into objects that will use it to get the DAO they need.
I think the best way to simplify this from a consumption perspective would be to define a strategy pattern, using a factory class or method:
public Dao<T, TId> GetDaoFor<T, TId>(T objectInstance) where T:EntityWithTypedId<TId>
{
//Here, you could use a Dictionary, Linq with some reflection, etc.
}
This one method can be injected as a delegate into classes dependent upon DAOs. The difference is that classes that need a DAO are dependent on a method that can give it to them, which can be provided by the IoC container; they are NOT dependent on the container itself (which is the primary source of evil inherent in the "service locator" pattern). This reduces the number of things you'd have to change if you re-wrote how you got these DAOs.
EDIT: A bit off-topic, but I opened the door:
The service location pattern is generally to be avoided, because it results in code that relies on the service locator. For instance, the following is common in code where the IoC has been exposed at child levels:
private IDependency _dependency;
public IDependency MyDependency
{
get {
_dependency = _dependency ?? IoC.Resolve<IDependency>();
return _dependency;
}
}
While this seems like a nice pattern (dependencies are lazily initialized, consuming code doesn't need to know about dependencies of the child, and you always* get a reference), this code will ALWAYS require the IoC singleton to exist. You can change the IoC framework behind it, you can remove the third-party tool altogether and roll your own, but this class will always require something on which to statically call Resolve<IDependency>().
You also don't ALWAYS get a reference; you get a reference only if you properly registered IDependency with IoC. This produces two more weaknesses; 1) you don't know what the class will need without opening it up, and 2) if/when the call fails, it will fail deep in the bowels of the dependent class' inner workings. If you develop a new class, and plug it into IoC, it may pass integration, and even work in production for a while, until you start getting weird "object reference set to null" errors in really weird places in code, which are, trust me, a nightmare to debug.
Lastly, unit-testing service-locator-pattern code is more difficult, for the simple reason that you must mock the service locator as well as the dependency provided by the service locator. You can leave the production service locator in use, and simply register mocked classes as the dependencies, but that's not a unit test; the test relies on, and thus to some extent tests, that the integration of the class and its service locator works as expected. That's an integration test.
By contrast, dependency injection patterns free you from any dependency on how dependencies are resolved. The only requirement (in constructor-injection) is that they be around when the class is created. This has several advantages:
If not using an IoC framework, you have to know what the class will need to instantiate it.
If using an IoC framework, you get a runtime error when attempting to instantiate the dependent class, not sometime later when the object actually gets resolved.
When testing a dependent class, you can more easily mock the dependency, because the dependency does not have to be fed in via the service locator.
You can in most IoC frameworks still lazily initialize dependencies by providing a factory method instead of the actual dependency to the constructor. The above pattern then calls that delegate, which could come from anywhere, instead of a static named method which is satisfied by one and only one construct in the entire codebase.