A Microsoft.Practices.Unity container will try to resolve any parameters that a constructor expects. However, for simple string (or int) parameters, that won't work. My example for this was a queue that expects a name parameter:
Public Class Queue
Private mName As String
Public Sub New (name As String)
mName = name
End Sub
End Class
This can be solved, and Microsoft explains how in this section of the documentation.
In this case it results in code like this:
MyContainer.Configure(Of InjectedMembers)() _
.ConfigureInjectionFor(Of Queue)( _
New InjectionConstructor("testqueue"))
Posts tonen met het label Dependency Injection. Alle posts tonen
Posts tonen met het label Dependency Injection. Alle posts tonen
dinsdag 3 maart 2009
dinsdag 18 november 2008
Using a Factory for resolving a dependency
Today I solved the gap between Dependency Injection with Unity and a Factory. What was the question?
We have a UseCaseFactory for creating instances of descendants of the UseCaseBase class. This factory internally uses the Microsoft Patterns & Practices Unity container for actually instantiating the requested class and its dependencies. When a UseCase is created, it gets it's own container.
To make things even more complex, we have UseCaseFactory.CreateChildUseCase, which results in a UseCase in the same container as the parent UseCase.
Some descendants - but not all - require repositories for data handling and therefore a Hibernate session. Currently there is a HibernateSessionFactory as well. The NewSession() method can provide you with a session.
The old solution was ugly: All UseCase classes that required a repository had to be derived from UseCaseWithRepositoriesBase. The CreateUseCase method would check on this. If true, then it created a Session with the HibernateSessionFactory and registered this instance in the container. After that, all necessary repositories (that depend on a session) could be resolved.
I did not want to completely change the creation of Hibernate session objects just to get rid of the factory. It took me a little while to find out what I really wanted: Register a method on a factory in the container to use when resolving the Hibernate session.
There are not many hits on it in Google, but it is possible. The Unity framework provides the StaticFactoryExtension exactly for this purpose. Here's how it works:
Imports Microsoft.Practices.Unity
Imports Microsoft.Practices.Unity.StaticFactory
Public Class UsecaseFactory
Private Shared mHibernateFactoryExtension As New StaticFactoryExtension()
Shared Sub New()
mRootContainer = New UnityContainer
mRootContainer.AddExtension(mHibernateFactoryExtension)
mHibernateFactoryExtension.RegisterFactory(Of HibernateSession)(AddressOf HibernateSessionFactory.CreateSession)
End Sub
End Class
Effectively you tell the container: If a HibernateSession instance is requested and it does not yet exist, call HibernateSessionFactory.CreateSession to create it for you.
You have to provide the RegisterFactory method with a delegate of type FactoryDelegate:
Public Delegate Function FactoryDelegate(ByVal container As Microsoft.Practices.Unity.IUnityContainer) As Object
Although you get the container as a parameter, you need not register the result yourself. You just have to return the requested object (in this case a HibernateSession object). It will automatically be registered in the container. The container is probably just there for your convenience in case you need to resolve other classes along the way.
We have a UseCaseFactory for creating instances of descendants of the UseCaseBase class. This factory internally uses the Microsoft Patterns & Practices Unity container for actually instantiating the requested class and its dependencies. When a UseCase is created, it gets it's own container.
To make things even more complex, we have UseCaseFactory.CreateChildUseCase, which results in a UseCase in the same container as the parent UseCase.
Some descendants - but not all - require repositories for data handling and therefore a Hibernate session. Currently there is a HibernateSessionFactory as well. The NewSession() method can provide you with a session.
The old solution was ugly: All UseCase classes that required a repository had to be derived from UseCaseWithRepositoriesBase. The CreateUseCase method would check on this. If true, then it created a Session with the HibernateSessionFactory and registered this instance in the container. After that, all necessary repositories (that depend on a session) could be resolved.
I did not want to completely change the creation of Hibernate session objects just to get rid of the factory. It took me a little while to find out what I really wanted: Register a method on a factory in the container to use when resolving the Hibernate session.
There are not many hits on it in Google, but it is possible. The Unity framework provides the StaticFactoryExtension exactly for this purpose. Here's how it works:
Imports Microsoft.Practices.Unity
Imports Microsoft.Practices.Unity.StaticFactory
Public Class UsecaseFactory
Private Shared mHibernateFactoryExtension As New StaticFactoryExtension()
Shared Sub New()
mRootContainer = New UnityContainer
mRootContainer.AddExtension(mHibernateFactoryExtension)
mHibernateFactoryExtension.RegisterFactory(Of HibernateSession)(AddressOf HibernateSessionFactory.CreateSession)
End Sub
End Class
Effectively you tell the container: If a HibernateSession instance is requested and it does not yet exist, call HibernateSessionFactory.CreateSession to create it for you.
You have to provide the RegisterFactory method with a delegate of type FactoryDelegate:
Public Delegate Function FactoryDelegate(ByVal container As Microsoft.Practices.Unity.IUnityContainer) As Object
Although you get the container as a parameter, you need not register the result yourself. You just have to return the requested object (in this case a HibernateSession object). It will automatically be registered in the container. The container is probably just there for your convenience in case you need to resolve other classes along the way.
Abonneren op:
Posts (Atom)