Can an abstract class constructor instantiate a new object? - c#

I have a group of services that get injected into my controllers. Can my abstract class constructor instantiate new instances of commonly used objects?
public class ReportService : AReportService, IReportService
{
private readonly IMyService _myservice;
public ReportService(IMyService myService) : base ()
{
_myservice = myService;
}
public void MyMethodForThisService(string someProperty)
{
_parentService.DoSomething(someProperty);
}
}
public abstract class AReportService
{
protected readonly ParentService _parentService;
protected AReportService()
{
_parentService = new ParentService();
}
protected void MyFirstSharedMethodForAllServices(string someProperty)
{
_parentService.DoSomethingElse(someProperty);
}
}

Jon Skeet (as usual) is correct--you can do this. However, since you're following a Dependency Injection pattern with your child controllers, you should probably use dependency injection for your parent class as well.
You can do this by injecting the dependency into the parent's constructor, but as you've probably noticed that requires all the child classes to inject the same object and do a pass-through, which can get annoying as you add more dependencies.
Alternatively, you can do Property Injection, but this can make it easy to forget to update unit tests with new properties that need to be injected.
As a compromise, I'll often use Method injection, where the base class has an "InjectDependencies" method that initializes the dependencies. Unfortunately, this disallows you from making your dependencies read-only, and still makes it possible to construct your object without providing dependencies.
A final option would be to create a special class just for containing the parent class's dependencies, and then inject that class into the parent class's constructor. Child classes then need only pass through a single parameter into the parent constructor, and you're free to add dependencies in the future, which will not affect the child classes, but will alert unit tests that try to construct the dependency object by hand.
You should also think carefully about whether you're using inheritance in a situation where you should be using composition. Is MyFirstSharedMethodForAllServices() just a convenience method that you happen to know that several services will use? Why not just create a separate class with this method, which all of those services can inject? This would give you more flexibility, for example, to unit test MyFirstSharedMethodForAllServices() independently. It also leaves your services free to extend some other class based on a more "is a"-style relationship.

Can my abstract class constructor instantiate new instances of commonly used objects?
Absolutely. The constructor for an abstract class can do basically anything a normal constructor can. The only restriction is that you can only call the constructor as part of chaining from another constructor.

Related

How to supply dependencies to classes that are created by a factory class?

Let's say I have an interface named ICustomer that defines one method startProcessing():
interface ICustomer
{
void startProcessing(byte[] data);
}
Now, I have multiple concrete classes like ProductA_User and ProductB_User. Each one has different properties but they all implement ICustomer as they are all customers:
class ProductA_User : ICustomer
{
string _name;
IRepository _repo;
public ProductA_User(string name)
{
_name = name;
}
public void startProcessing(byte[] data)
{
Console.WriteLine(_name);
var temp = _repo.Get<VModel>(filter: x.CName == _name).ToList();
}
}
class ProductB_User : ICustomer
{
public void startProcessing(byte[] data)
{
throw new System.NotImplementedException();
}
}
I am invoking a shared method in a factory class named MemberFactory and creating object based on productType.
enum ProductTypeEnum { ProductA, ProductB }
class MemberFactory
{
ICustomer Create(ProductTypeEnum productType)
{
switch (productType)
{
case ProductTypeEnum.ProductA: return new ProductA_User("Steve");
case ProductTypeEnum.ProductB: return new ProductB_User();
default: return null;
}
}
}
I give it as param of the enum. Since each concrete class is different but implements ICustomer, I am able to return an instance that implements ICustomer. In ProductA_User() I am trying to inject _repo which is nothing but EF repo.
what I should do? I don't want to pass extra parameter (_repo) to create object of class. how can I get any injection done to my concreate class?
Somewhere you have a class that needs an ICustomer. You don't want that class to know anything about the implementation of ICustomer, so you're using MemberFactory.
But if the class that needs ICustomer has to create MemberFactory and pass arguments to it like an IRepository, then you're back to the same problem again. The class that needs ICustomer shouldn't know that some implemenations of ICustomer need an IRepository.
There are a lot of approaches to this. I'll go with a simple and direct one.
First, create an interface for MemberFactory:
interface IMemberFactory
{
ICustomer Create(ProductTypeEnum productType)
}
Change the declaration of MemberFactory so that it implements the interface:
class MemberFactory : IMemberFactory
Wherever you were injecting MemberFactory, inject IMemberFactory instead.
Now the class that depends on IMemberFactory won't know anything about its implementation. It just knows that it has an IMemberFactory and calls its Create method.
Then, inject the IRepository into the implementation, MemberFactory.
class MemberFactory
{
private readonly IRepository _repository;
public MemberFactory(IRepository repository)
{
_repository = repository;
}
ICustomer Create(ProductTypeEnum productType)
{
switch (productType)
{
case ProductTypeEnum.ProductA: return new ProductA_User("Steve");
case ProductTypeEnum.ProductB: return new ProductB_User();
default: return null;
}
}
}
Now if MemberFactory needs an IRepository to create certain types of ICustomer, it has one. This is not perfect. It could get out of hand if we added more and more dependencies this way. But it's a start.
Then, whatever type needs the IMemberFactory to create ICustomer, inject the IMemberFactory into that:
class SomeClassThatNeedsMemberFactory
{
private readonly IMemberFactory _memberFactory;
public SomeClassThatNeedsMemberFactory(IMemberFactory memberFactory)
{
_memberFactory = memberFactory;
}
}
Now each class has its dependencies injected into it. As a result, a class isn't responsible for creating its own dependencies. That means it doesn't know anything about the concrete implementation of the dependencies. SomeClassThatNeedsMemberFactory doesn't know that the concrete implementation might need an IRepository. All it knows about IMemberFactory is the interface.
That's a big part of dependency injection. Now if we change the implementation of IMemberFactory, its consumers don't need to know about it. They don't know what gets passed to its constructor.
It also makes each class easier to test. If you're testing SomeClassThatNeedsMemberFactory, you can mock IRespository.
I haven't mentioned dependency injection/IoC containers yet because you didn't ask about them, and because they aren't actually central to the concept of dependency injection. Dependency injection is about constructing classes or methods so that they receive dependencies instead of creating them - all the stuff above. A container just helps us to manage all that.
Suppose we're working with IServiceCollection/IServiceProvider which is sort of the default container these days for .NET applications.
We can do this if we're working in the Startup class of a web application, or something similar for other application types.
void ConfigureServices(IServiceCollection services)
{
services.AddScoped<SomeClassThatNeedsMemberFactory>();
services.AddScoped<IMemberFactory, MemberFactory>();
services.AddScoped<IRepository, SomeConcreteRepository>();
}
This tells the service collection
We're going to ask it to create instances of SomeClassThatNeedsMemberFactory.
If it's creating anything that needs an instance of IMemberFactory, create an instance of MemberFactory.
If it's creating anything that needs an instance of IRepository, use SomeConcreteRepository.
Now suppose the application needs to create an instance of a Web API controller, and we've injected SomeClassThatNeedsMemberFactory of that controller. The service provider (dependency injection/IoC container) will say
I need to create an instance of FooController. The constructor says that it needs an instance of SomeClassThatNeedsMemberFactory, so I'll create one of those.
Wait, the constructor for SomeClassThatNeedsMemberFactory needs an instance of IMemberFactory. When I'm asked for IMemberFactory I use MemberFactory, so I'll create one of those.
Wait, the constructor for MemberFactory needs an instance of IRepository. I'll create an instance of SomeConcreteRepository.
As long as we've told it what types to use, it can create complex objects where the dependencies have dependencies that need more dependencies, and so on. But we don't have to think so hard about that. We can just look at one class at a time and pay attention to what dependencies it needs as we're writing it, working on it, or testing it.
That's why containers are so popular. We could do all this without them, but it's harder. They are not, however, what dependency injection is all about. They just enable it.

Using dependency injection how can I access a method in a class inside a service?

I am using the Microsoft.Extensions.DependencyInjection 5.0.1 nuget package.
Here's the Dependency Injection service that I created:
public partial class BehaviorService : IBehaviorService
{
public BehaviorService()
{
}
public class MyClass : MyClassBase
{
public void MyMethod()
{
}
}
}
public interface IBehaviorService
{
}
As MyClass inherits from MyClassBase, I was thinking it was best to put that inside of a service—but I am very new to DI, so maybe it should be it's own service? I hope I can get advice here.
What I am not sure how to do is access the method inside the MyClass class that's inside of my BehaviorService, and how can I identify that in my interface?
Note: To access the service, I was thinking to use something like:
var x = Startup.ServiceProvider.GetRequiredService<BehaviorService>();
There are a few conceptual problems here that you’re going to run into. I’m going to approach the problem from the outside in, eventually getting down to your specific question. The short answer to your immediate question, though, is that you either need to register and consume MyClass as its own service, or you need to instantiate and expose it from BehaviorService, and communicate that via your IBehaviorService interface. Before you get there, though, you’ll want to work through the broader conceptual problems discussed below.
Constructor Injection
Your dependencies should be passed into consuming class via the constructor, and wired up by your dependency injection container (i.e., the Microsoft dependency injection library). You should not call out to your dependency injection container from within your consuming class—by e.g. calling GetRequiredService()—as that just establishes a hard-coded dependency on your dependency injection container itself, while also obscuring the dependencies of your application from external callers.
Note: Calling to your dependency injection container from within a consuming class is known as the service locator pattern, and it’s usually regarded as an anti-pattern.
Code to Interfaces
The dependency passed into your consuming class’s constructor should be your IBehaviorService interface, and that’s all your consuming class should ever be aware of. That means your consuming class has no awareness of implementation details that are specific to your concrete BehaviorService class unless they’re reflected in the IBehaviorService interface. This allows you to swap out implementations without maintaining a dependency on any one concrete implementation—which is the primary goal of dependency injection. Currently, your IBehaviorService contains no members, so there’s nothing consuming classes can do to interact with it.
Note: Acknowledging that part of your question is how to expose your nested method via your interface—I’ll circle back to that below.
Accessing a Nested Class
There are three basic ways of accessing your nested MyClass class:
Establish an interface for it, register it with your dependency injection container, and inject it into a consuming class via the injector—i.e., to treat it exactly like an independent service.
Do the same as the above, but inject it into BehaviorService instead of your consuming class. That makes sense if BehaviorService relies on MyClass, but your consuming class doesn’t—which doesn’t sound like the case here.
Have your parent BehaviorService class create and expose an instance of MyClass via a member registered on the IBehaviorService. In this case, that member needs to be added to your IBehaviorService interface.
Of these, the first should be your preference unless BehaviorService depends on MyClass, in which case the second should be your preference. If both your consuming class and BehaviorService depend on MyClass then it should be injected into both. Finally, there are a lot of potential issues with the last option, so I’d avoid it; if you need to expose another class from a dependency, it should either be a well-known class (e.g., in the same project as your interface), or should adhere to an interface or base class which is.
Nested Classes vs. Services
Critically, in any of these cases, there is no real need or benefit to having MyClass nested; the same options are available if it were a separate class. From dependency injection’s perspective, it doesn’t really matter either way. So the question you should be asking yourself is what problem are you trying to solve by nesting it?
(Personally, I very rarely find cases where a nested classes are desirable—and especially public nested classes—but I don’t know your use case.)
Accessing Just a Nested Method
The above assumes you want to access the nested class. If you really only care about the method on the nested class, and only need it it context of your service, then the simpler approach is for your interface expose that method:
public interface IBehaviorService
{
void MyMethod();
}
And then have your BehaviorService proxy a request to an instance of the nested class:
public partial class BehaviorService : IBehaviorService
{
private readonly MyClass myClass;
public BehaviorService()
{
myClass = new MyClass();
}
public void MyMethod() => myClass.MyMethod();
private class MyClass : MyClassBase
{
public void MyMethod()
{
}
}
}
In this case, neither your interface or your consumers need to be aware of the existence of the nested class—and, in fact, you might even be able to mark it as private. Your BehaviorService is effectively acting as a facade to the nested class. This works well if a) MyClass is really specific to your BehaviorService implementation, and/or b) you only need access to a couple of members of MyClass.

How to register collection of instances in Simple injector

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);

ImportingConstructors & Subclasses

I have an abstract base class, and a derived class. I'm trying to use MEF to inject a reference to to my WindowManager, by using [ImportingConstructor], in the base class.
ie.
[ImportingConstructor]
public SomeViewModel(IWindowManager windowmanager) {...}
The issue is that before I added this, all I had was no param constructors, and the derived class is complaning about If I add a no param constructor to the base class, the WindowManager never gets injected.
Using my currently limited knowledge the only way I can think of is to change the manager import to a Property Import, and just have a no param default constructor. This kind of bugs me, as the general rule seems to prefer constructor injection for required dependencies, and property injection for optional ones.
I could add overriding [ImportingConstructor]s in my subclasses, but that seems like unnecessary duplication of code.
Is there a nicer way to do this, ie making sure my dependencies are getting injected in when the derived classes are created?
Ignore MEF for a moment and consider this:
public abstract class BaseClass {
protected BaseClass(IService service) { }
}
public class SubClass : BaseClass {
public SubClass(IService service) : base(service) { }
}
Because the base class defines a single constructor, the subclass must initialise the base class, by providing an argument for the base class' constructor.
Now, with MEF, what I think you are trying to do is this:
public abstract class BaseClass {
[ImportingConstructor]
protected BaseClass(IService service) { }
}
[Export]
public class SubClass : BaseClass {
public SubClass() { }
}
It sounds like you are trying to inject something into the constructor of the base class, but you can't do that, because its the resposibility of the subclass to ensure the appropriate arguments are passed to the base class of the constructor. You need to make a modification to your subclass:
[Export]
public class SubClass : BaseClass {
[ImportingConstructor]
public SubClass(IService service) : base(service) { }
}
Now the subclass will have the service injected and will pass it to the base class.
In terms of using Property Injection vs Constructor Injection: it is preferable to initialise a type into a usable state. That being any explicit dependencies should be required in the constructor. But, because MEF will satisfy all imports, by the time you've got your part back from the container, both constructor and property injections would have already occurred, so you could potentially use property imports instead. My preference has always been to go with constructor imports.

how do IoC this?

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.

Categories

Resources