Following the article: http://www.udidahan.com/2009/06/14/domain-events-salvation/
we can see that DomainEvents implemantation uses DI container
public static IContainer Container { get; set; }
and then
if(Container != null) {
foreach(var handler in Container.ResolveAll<Handles<T>>()) handler.Handle(args);
}
Should I integrate DI container inside the same assembly I store domain objects or can I externalize/abstract away the Container.ResolveAll<Handles<T>>()? (In my previous experiences I put all DI-related stuff inside global.asax.cs).
Technically I'm familiar only with Ninject DI container but probably will understand the concept so your advices/illustrations are appreciated.
Thanks!
No it is not necessary. I'd make DomainEvents and its methods non-static and use the container to create it. A decent container will create and initialize the Handles and their dependencies and allow you to call the event handlers without any reference to the container.
The only catch is the registration of the event handlers. For that I use Bootstrapper to call instances of IUnityRegistration and configure UNITY. I started to use CommonServiceLocator to reduce dependencies. And even more recently, I switched to MEF to get rid of the registration classes all together.
Related
I have a class library for caching ( Redis ), we have a unity container inside this Redis class library
public class TCache<T>
{
static readonly IUnityContainer container = new UnityContainer();
private ITCache<T> ICacheStore;
static TCache()
{
container.RegisterType<ITCache<T>, TRedisCacheStore<T>>(new ContainerControlledLifetimeManager());
}
public TCache()
{
ICacheStore = container.Resolve<TRedisCacheStore<T>>();
}
Now my senior said me not use a separate container like this and I should be using the container which is already created inside the web app with the reason being that there should be only one single container.
My question is: is it possible to access a unity container that resides in a different project and is it necessary to do this change ?
Note: I cannot add the reference of the web app into the Redis cache class library.
You should only reference a container within your composition root (http://blog.ploeh.dk/2011/07/28/CompositionRoot/).
In other words, find where your current services are registered, and perform the generic registration there.
Your type that requires a cache store then takes your abstraction via constructor injection:
public class Cache<T>
{
private readonly ITCache<T> cacheStore;
public Cache(ITCache<T> cacheStore)
{
this.cacheStore = cacheStore
?? throw new ArgumentNullException(nameof(cacheStore));
}
}
By the way, using T as a prefix for your types (rather than as a prefix for generic type parameters) is very confusing.
The names TCache and ITCache are also very confusing.
Well, I share his view of the usage of the container. How I fixed this issue is (without going into the details of how I actually created it):
Make an option to register onto the container through an interface. Something like IRegisterContainer.Register(IUnityContainer container).
Then at the moment where you now register the mappings to the container, you extend that function to also search your assembly for all objects that implement that IRegisterContainer and make them register themselves.
And use this as a platform to fix your problem.
If you want to use the IUnityContainer in your TCache object to resolve the TRediscacheStore. Simply let the IUnityContainer register itself.
container.Register<IUnityContainer, container>().
And make it a dependency in the constructor of TCache.
I am facing problem with disposing unnecessary objects from DI container. I use Prism for Xamarin.Forms with Unity container.
Application gets configuration from some database, creates some services using this configuration and registers this services in container using ContainerControlledLifetimeManager. This services are used while resolving views and viewmodels.
When configuration changes application retrieves again changed configuration and now problem comes: how can I remove previous registrations and register new services? If I simply re-register service then previous service is not GC-ed until disposing container.
I cannot dispose container, because it is created and managed by Prism (can I?).
I cannot use child container because Prism will not resolve views and viewmodels using child container (can I?)
Should I use different DI? Does Autofac or other DI support such approach?
EDIT:
I just have tested disposing of re-registered objects in Unity. It came out that re-registering using:
Container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager())
really releases previously registered objects. But I have also registrations using just type:
Container.RegisterType<Foo>(new ContainerControlledLifetimeManager())
or using instance:
Container.RegisterInstance(new Foo())
and these objects are not released when re-registering.
So now the only solution is to reconstruct the Unity container? Or give a try to other ioc container?
Without knowing all of the specifics of what you are looking to accomplish it's impossible to give you a solid roadmap, so I'll touch on some things to consider.
Reregistering Services
If you have some service IFoo, and two implementations FooA and FooB and you initially registered FooA as the implementation for IFoo (with a container controlled lifetime, registering FooB with the container should dispose of the FooA instance and FooB should be generated going forward.
Reconstructing the container
If you have to reconstruct the Container, it should possible. I haven't ever run into a use case where I have had to try something like what you are looking to do. For starters you probably want to take a look at the Initialize method from PrismApplicationBase. This is where the container gets constructed and setup. To handle the reconstruction, you will want to create an event that you subscribe to in your App class.
public partial class App
{
protected override void OnInitialized()
{
var ea = Container.Resolve<IEventAggregator>();
ea.GetEvent<SettingsChangedEvent>().Subscribe(OnSettingsChangedEvent);
// navigate
}
private void OnSettingsChangedEvent()
{
var ea = Container.Resolve<IEventAggregator>();
// prevent a memory leak
ea.GetEvent<SettingsChangedEvent>().Unsubscribe(OnSettingsChangedEvent);
// If you need platform specific types be sure to register either the
// IPlatformInitializer or some similar helper
var platformInitializer = Container.Resolve<IPlatformInitializer>();
ModuleCatalog = CreateModuleCatalog();
ConfigureModuleCatalog();
Container = CreateContainer();
ConfigureContainer();
// This would be your original RegisterTypes, so this assumes you
// look at your settings when initially registering types.
RegisterTypes();
// See notes above
platformInitializer.RegisterTypes(Container);
NavigationService = CreateNavigationService();
InitializeModules();
// Your container is now reset.
var ea = Container.Resolve<IEventAggregator>();
ea.GetEvent<SettingsChangedEvent>().Subscribe(OnSettingsChangedEvent>()
}
}
Containers
As for choosing a container. There is nothing wrong with Unity. Just know that when you're working with Unity, you're going to be stuck with the way it is since it apparently it is a dead project now. Ninject for Prism Forms uses a PCL variant that doesn't seem to be maintained anymore, but when the switch to NetStandard is made Prism will be able to target the current version of Ninject. As for Autofac, there you are dealing with an immutable container so the moment you resolve something you cannot update any new registrations. Autofac for Prism Forms is also a version behind for the same reason as Ninject. DryIoc for Prism forms is a great container and actually the one I am using on all of my current projects. It is also being actively maintained so you can expect use cases you run into to at least be heard.
Thanks for help to Dan S. and R. Richards.
Recreating Prism container caused problems in navigation. Maybe it is possible to fix it but I do not know how.
Using different IOC container would require too much time to learn it.
I ended up with custom lifetime manager (the solution provided in R. Richards link):
class CustomLifetimeManager : LifetimeManager
{
private object _Value;
public override object GetValue()
{
return _Value;
}
public override void RemoveValue()
{
_Value = null;
}
public override void SetValue(object newValue)
{
_Value = newValue;
}
}
Above lifetime manager allows to remove registrations:
public static class UnityContainerExtension
{
/// <summary>
/// Removes registrations that were registred using <see cref="CustomLifetimeManager"/>
/// </summary>
/// <param name="container"></param>
public static void RemoveCustomLifetimeRegistrations(this IUnityContainer container)
{
var registrations = container.Registrations.Where(r => r.LifetimeManagerType == typeof(CustomLifetimeManager));
foreach(var r in registrations)
{
r.LifetimeManager.RemoveValue();
}
}
}
This is probably a bit trivial, but I must be doing something wrong. I have an MVC project, where I have two projects controlled by IoC using Windsor:
The MVC project
A project with services
Normally I would register the services using an XML file. However, I want to register all services and interfaces automatically.
All my services is placed in my services project called LetterAmazer.Business.Services, under the namespace LetterAmazer.Business.Services.Services. My interfaces, which the services derive from, is in the namespace LetterAmazer.Business.Services.Domain .
I have tried to set it up in my Global.asax, in the following way:
private void InitializeContainer()
{
var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
FilterProviders.Providers.Remove(oldProvider);
Container.Register(Component.For<IWindsorContainer>().Instance(this.Container));
Container.Install(new BootstrapInstaller());
Container.Register(
Classes.FromAssemblyInDirectory(new AssemblyFilter("LetterAmazer.Business.Services"))
.InNamespace("LetterAmazer.Business.Services.Services"));
Container.Install(new WebWindsorInstaller());
var provider = new WindsorFilterAttributeFilterProvider(this.Container);
FilterProviders.Providers.Add(provider);
DependencyResolver.SetResolver(new WindsorDependencyResolver(ServiceFactory.Container));
}
public IWindsorContainer Container
{
get { return ServiceFactory.Container; }
}
But this provides several issues. First of all, it doesn't find any services when running the Classes.FromAssemblyInDirectory call. Furthermore, this wouldn't get the interfaces.
So I am basically asking how to solve this problem in a best practice way? I have 30+ services, and I want them all, so it would make sense to add them by conventation rather than hand pick.
EDIT:
The code I ended up with:
var assembly = Assembly.LoadFrom(Server.MapPath("~/bin/LetterAmazer.Business.Services.dll")); ;
Container.Register(
Classes.FromAssembly(assembly)
.InNamespace("LetterAmazer.Business.Services.Services")
.WithServiceAllInterfaces());
I haven't used Classes.FromAssemblyInDirectory() method but I usually use FromThisAssembly() or 'FromAssemblyContaining()' methods to select assemblies. Simetimes FromAssembly("AssemblyName") is used.
I would write the following code the following way if there is no base interface for all seervices:
container.Register(
Classes.FromAssembly("LetterAmazer.Business.Services")
.InNamespace("LetterAmazer.Business.Services.Services")
.WithServiceAllInterfaces());
If there is a generic interface IService<T> I would use the following registration:
container.Register(
Classes.FromAssembly("LetterAmazer.Business.Services")
.BasedOn(typeof(IService<>))
.WithServiceAllInterfaces());
I'd like to add that all your services will be registered as Singletons if life style is not specified during registration.
You can find detailed information in the article Registering components by conventions from Castle Windsor website.
I am designing a simple plugin framework a for a .NET 3.5 application (WinForms).
Our current application needs to start supporting dynamic loading and "hooking" of different "plugins" / "extensions" that are unknown to the application at compile time.
These extensions would be "hooked" into different areas of the application, such as aded as event handlers of certain classes.
For example (simplified):
public class SomeSystem
{
public event Action<string> Completed;
public event Action<string> Failed;
public event Action<string> Stopped;
}
One use case I'd like to have is for developers to be able to define handlers for such events in a plugin assembly, without having the application know about them.
From my knowledge, IoC containers allow dynamically discovering objects at runtime and registering them in a container.
Is an IoC container able to also do this hooking into various events for me? Or is this task easier to do without such a framework?
How does one go about designing how to integrate an IoC container for such a task? (suppose that there are multiple extension points, such as different events that can be used to register on).
Some questions i found myself asking :
Is it common that the plugin itself offer a Register method to do the registration?
Should the IoC do the registration? (how is that usually done?)
How can extension points be easily defined when using an IoC container ?
You probably want to look at MEF. It allows all of the things you have asked about. The terminology it uses (ComposableParts, Exports, etc) is initially confusing, but it's very straightforward to use.
Is it common that the plugin itself offer a Register method to do the
registration?
MEF makes the application do the work of finding and registering plugins. The plugin only needs to implement an interface that states "I am a plugin that can do X".
Should the IoC do the registration? (how is that usually done?)
An application that will consume MEF plugins is able to specify how it will load the plugins. This could be by searching a directory for DLLs, reading the configuration file for a list of assembly names, checking the GAC - anything at all. It's totally extensible (in that you can write your own search classes)
How can extension points be easily defined when using an IoC container
?
MEF uses interfaces to define a Contract between the application and plugin.
This answer will be specific to my container.
Our current application needs to start supporting dynamic loading and "hooking" of different "plugins" / "extensions" that are unknown to the application at compile time.
To be able to do that you have to define some extension interfaces which you place in a class library which will be shared between your application and all of your plugins.
For instance, if you would like your applications to be able to add stuff to the application menu you could create the following interface:
class ApplicationMenu
{
// The "File" menu
IMenuItem File { get; }
}
interface IMenuRegistrar
{
void Register(ApplicationMenu menu);
}
Which means that your plugin can create the following class:
[Component]
public class CoolPluginMenuRegistrar : IMenuRegistrar
{
public void Register(ApplicationMenu menu)
{
menu.File.Add("mnuMyPluginMenuName", "Load jokes");
}
}
The [Component] attribute is used by my container so that it can discover and automatically register classes for you.
All you need to do to register all extension points like the one above is this:
public class Program
{
public static void Main(string[] args)
{
var registrar = new ContainerRegistrar();
registrar.RegisterComponents(Lifetime.Transient, Environment.CurrentDirectory, "MyApp.Plugin.*.dll");
var container = registrar.Build();
// all extension points have been loaded. To load all menu extensions simply do something like:
var menu = GetMainMenu();
foreach (var registrar in container.ResolveAll<IMenuRegistrar>())
{
registrar.Register(menu);
}
}
}
These extensions would be "hooked" into different areas of the application, such as aded as event handlers of certain classes. From my knowledge, IoC containers allow dynamically discovering objects at runtime and registering them in a container.
Yep. You get all of that.
Is an IoC container able to also do this hooking into various events for me? Or is this task easier to do without such a framework?
Yes. I got a built in event mechanism. Put the event classes (regular .NET classes in shared class librararies). The simply subscribe on them by implementing an interface:
[Component]
public class ReplyEmailNotification : ISubscriberOf<ReplyPosted>
{
ISmtpClient _client;
IUserQueries _userQueries;
public ReplyEmailNotification(ISmtpClient client, IUserQueries userQueries)
{
_client = client;
_userQueries = userQueries;
}
public void Invoke(ReplyPosted e)
{
var user = _userQueries.Get(e.PosterId);
_client.Send(new MailMessage(user.Email, "bla bla"));
}
}
And to publish events:
DomainEvent.Publish(new ReplyPosted(user.Id, "This is a subject"));
The events can be handled by any plugin as long as they:
Can access the event class
Have been registered in the container ([Component] or manual registration)
Implements ISubscriberOf<T>
Is it common that the plugin itself offer a Register method to do the registration?
Yep. Through different interfaces which are defines as extension points in a shared assembly.
Should the IoC do the registration? (how is that usually done?)
Yes. If the container provides it.
How can extension points be easily defined when using an IoC container ?
You can read about it in more detail here: http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container
we want to use Unity for IOC.
All i've seen is the implementation that there is one global static service (let's call it the the IOCService) which holds a reference to the Unity container, which registers all interface/class combinations and every class asks that object: give me an implementation for Ithis or IThat.
Frequently i see a response that this pattern is not good because it leads to a dependency from ALL classes to the IOCService (not to the Unity container because it is only known inside the IOCService).
But what i don't see often, is: what is the alternative way?
Michel
EDIT: found out that the global static service is called the service locator, added that to the title.
The alternative is to have a single instance of your container at the highest application level only, then use that container to resolve every object instance you need to create in that layer.
For example, the main method of most executables just looks like this (minus exception handling):
private static void main(string[] args) {
Container container = new Container();
// Configure the container - by hand or via file
IProgramLogic logic = container.Resolve<IProgramLogic>();
logic.Run();
}
Your program (represented here by the IProgramLogic instance) doesn't have to know anything about your container, because container.Resolve will create all its dependencies - and its dependencies' dependencies, on down to leaf classes with no dependencies of their own.
ASP.NET is a harder case, because web forms doesn't support constructor injection. I typically use Model-View-Presenter in my web forms applications, so my Page classes really only have one dependency each - on their presenter. I don't unit test them (everything interesting and testable is in my presenters, which I do test), and I don't ever substitute presenters. So I don't fight the framework - I just expose a container property on my HttpApplication class (in global.asax.cs) and use it directly from my Page files:
protected void Page_Load(object sender, EventArgs args) {
ICustomerPresenter presenter = Global.Container.Resolve<ICustomerPresenter>();
presenter.Load();
}
That's service locator of course - though the Page classes are the only thing coupled to the locator: your presenter and all of its dependencies are still fully decoupled from your IoC container implementation.
If you have a lot of dependencies in your Page files (that is, if you do not use Model-View-Presenter), or if it's important to you to decouple your Page classes from your Global application class, you should try to find a framework that integrates into the web forms request pipeline and use property injection (as suggested by Nicholas in the comments below) - or write your own IHttpModule and perform the property injection yourself.
+1 for knowing that Service Locator is a Bad Thing.
Problem is - Unity is not very sophisticated so I don't know how easy/hard is it to do IoC the right way with it.
I wrote few blogposts recently that you might find useful.
How I use IoC Containers
Pulling from the container
Instead of using the container explicitly, use it implicitly by leveraging constructor / property injection instead. Create a core class (or set of core classes) that depend on all the major pieces of your application.
Most containers will let you put ISomething[] in your constructor and it will inject all instances of ISomething into your class.
This way, when you bootstrap your application:
Instantiate your container
Register all your goodies
Resolve the core classes (this will pull in all the other dependencies you need)
Run the "main" part of the application
Now, depending on the type of application you are writing, there are different strategies for avoiding marking the IoC container as "static".
For ASP.NET web applications, you'll probably end up storing the container in the Application State. For ASP.NET MVC applications, you need to change out the Controller Factory.
For desktop applications, things get more complicated. Caliburn uses an interesting solution to this problem using the IResult construct (this is for WPF applications but could be adapted for Windows Forms as well.
In theory, to not have to worry about having a static IoC instance, you need to follow the Fight Club Rule - i.e. not to talk about the fight club - i.e. not to mention the IoC container.
This means that your components should largely be unaware about the IoC container. It should only be used at the topmost level when registering components. If a class needs to resolve something, it should really be injected as a dependency.
The trivial case is easy enough. If PaymentService depends on IAccount, the latter should be injected by IoC:
interface IAccount {
Deposit(int amount);
}
interface CreditCardAccount : IAccount {
void Deposit(int amount) {/*implementation*/}
int CheckBalance() {/*implementation*/}
}
class PaymentService {
IAccount account;
public PaymentService (IAccount account) {
this.account = account;
}
public void ProcessPayment() {
account.Deposit(5);
}
}
//Registration looks something like this
container.RegisterType<IAccount, CreditCardAccount>();
container.RegisterType<PaymentService>();
The not so trivial case is where you want to inject multiple registrations. This especialy applies when you are doing any sort of Converntion Over Configuration and creating an object from a name.
For our payment example, say you want to enumerate through all accounts and check their balances:
class PaymentService {
IEnumerable<IAccount> accounts;
public PaymentService (IEnumerable<IAccount> accounts) {
this.accounts = accounts;
}
public void ProcessPayment() {
foreach(var account in accounts) {
account.Chackbalance();
}
}
}
Unity has the ability to register multiple interface to class mappings (they have to have different names thought). It does not, however, automatically inject those into classes that take collections of those registered interfaces. So, the above example will throw a resolution failed exception at runtime.
If you don't care that those objects live forever, you can register PaymentService in a more static fashion:
container.RegisterType<PaymentService>(new InjectionConstructor(container.ResolveAll<IAccount>()));
The above code will register PaymentService and will use a collection of IAccount instances that is resolved at registration time.
Alternatively, you can pass an instance of the container itself as a dependency and let PaymentService perform resolution of accounts. This is not quite following the Fight Club Rule, but is slightly less smelly than static Service Locator.
class PaymentService {
IEnumerable<IAccount> accounts;
public PaymentService (IUnityContainer container) {
this.accounts = container.ResolveAll<IAccount>();
}
public void ProcessPayment() {
foreach(var account in accounts) {
account.Chackbalance();
}
}
}
//Registration is pretty clean in this case
container.RegisterType<IAccount, CreditCardAccount>();
container.RegisterType<PaymentService>();
container.RegisterInstance<IUnityContainer>(container);
If your concern is having a dependency on Unity throughout your application, you can combine the service locator with a facade to hide the IOC implementation. In this way, you do not create a dependency on Unity in your application, only on having something that can resolve types for you.
For example:
public interface IContainer
{
void Register<TAbstraction,TImplementation>();
void RegisterThis<T>(T instance);
T Get<T>();
}
public static class Container
{
static readonly IContainer container;
public static InitializeWith(IContainer containerImplementation)
{
container = containerImplementation;
}
public static void Register<TAbstraction, TImplementation>()
{
container.Register<TAbstraction, TImplementation>();
}
public static void RegisterThis<T>(T instance)
{
container.RegisterThis<T>(instance);
}
public static T Get<T>()
{
return container.Get<T>();
}
}
Now all you need is an IContainer implementation for your IOC container of choice.
public class UnityContainerImplementation : IContainer
{
IUnityContainer container;
public UnityContainerImplementation(IUnityContainer container)
{
this.container = container;
}
public void Register<TAbstraction, TImplementation>()
{
container.Register<TAbstraction, TImplementation>();
}
public void RegisterThis<T>(T instance)
{
container.RegisterInstance<T>(instance);
}
public T Get<T>()
{
return container.Resolve<T>();
}
}
Now you have a service locator that is a facade for IOC services, and can configure your service locator to use Unity or any other IOC container. The rest of the application has no dependency on the IOC implementation.
To configure your service locator:
IUnityContainer unityContainer = new UnityContainer();
UnityContainerImplementation containerImpl = new UnityContainerImplementation(unityContainer);
Container.InitializeWith(containerImpl);
For testing, you can create a stub of IContainer that returns whatever you want, and initialize Container with that.