I’m using Autofac and want to resolve the correct implementation of the current assembly
I have a DataContextFactory Interface and Class:
Public Interface IDataContextFactory
Inherits IDisposable
Function GetDataContext() As IDataContext
End Interface
and the Implementation of the Interface
Public Class CDataContextFactory
Implements IDataContextFactory
Private m_oDbContext As IDataContext
Public Sub New(ByVal i_oDbContext As IDataContext)
m_oDbContext = i_oDbContext
End Sub
Public Function GetDataContext() As CoreData.IDataContext Implements CoreData.IDataContextFactory.GetDataContext
Return m_oDbContext
End Function
End Class
So now I have in every registered assembly different IDataContext Implementations. For example I have an assembly called ReportData with the data context
Public Class CReportDataContext
Inherits DbContext
Implements IDataContext
---
End Class
And also one implementation inside an other Assembly CommonData
Public Class CFacadeDataContext
Implements IDataContext
---
End Class
Then I have in every Assembly an implementation of my IRepository. For example
Public MustInherit Class CBaseReadRepository(Of T As {IEntity, Class})
Implements IReadRepository(Of T)
Private m_oDataContextFactory As IDataContextFactory
Private m_oDataContext As IDataContext
Protected ReadOnly m_oObjectDataSet As CQuery(Of T)
Public Sub New(ByVal i_oDataContextFactory As IDataContextFactory)
m_oDataContextFactory = i_oDataContextFactory
m_oObjectDataSet = DataContext.ObjectDataSet(Of T)()
End Sub
----
End Class
So how can I solve that the DataContextFactory will resolve the CReportDataContext inside the Assembly ReportData and the CFacadeDataContext inside the Assembly CommonData
Here is my ContainerBuilder registration:
Dim builder As New ContainerBuilder()
Dim oData = Assembly.Load("ReportData")
builder.RegisterAssemblyTypes(oData).Where(Function(t) t.Name.EndsWith("DataContext")).As(Of IDataContext) _
.AsImplementedInterfaces.SingleInstance
oData = Assembly.Load("CommonData")
builder.RegisterAssemblyTypes(oData).Where(Function(t) t.Name.EndsWith("DataContext")) _
.AsImplementedInterfaces().SingleInstance
builder.RegisterAdapter(Of IDataContext, IDataContextFactory)(Function(x) New CDataContextFactory(x))
Thanks
Autofac doesn’t have built-in support for this sort of use case. Generally it’s recommended that you try not to tie specific implementations to consumers because that breaks the whole IoC pattern – you may as well “new-up” the dependency type you need right in the class rather than injecting it.
If you absolutely must tie them together, you only have a couple of options. Neither is pretty, and both will require you to change the way you register things – you may not be able to do the
RegisterAssemblyTypesassembly scanning like you do now.First, you could use named registrations. When you register your
IDataContext, you give it a name. When you register your consuming class, you tell the builder which named instance you expect to use.Second, you could register an expression rather than a type for the consumer:
Finally, you could create a special module that does the work of figuring out which assembly the consumer is coming from and try to match it to a corresponding
IDataContext. This is more “automatic” but is a lot more complex. A stub might look like this:Like I said, not pretty.
If you have the ability to influence your design, it might be easier to make marker interfaces, like:
And then in your constructors take the specific interface:
That way type resolution would just work. (Marker interfaces aren’t the greatest pattern in the world, either, but it’s arguably better than tying individual implementations of things to specific consuming types.)