In StructureMap, how can I change the InstanceScope at runtime? - c#

In my DefaultRegistry I have this configuration:
ForRequestedType<INHUnitOfWork>().CacheBy(InstanceScope.HttpContext)
.TheDefault.Is.OfConcreteType<NHibernateUnitOfWork>();
At some point in the web application flow I want to change the InstanceScope to HttpSession to obtain a long conversation, so I do this:
PluginTypeConfiguration config = ObjectFactory.Model.PluginTypes.FirstOrDefault(p => p.PluginType.FullName.Contains("INHUnitOfWork"));
config.Lifecycle.EjectAll();
config.Lifecycle = StructureMap.Pipeline.Lifecycles.GetLifecycle(InstanceScope.HttpSession);
This seems to replace the initial InstanceScope, unfortunately it lasts only for the current request. When the next request arrives, the initial configuration is active again and the session information is lost.
Later I also want to be able to revert the change with something like this:
PluginTypeConfiguration config = ObjectFactory.Model.PluginTypes.FirstOrDefault(p => p.PluginType.FullName.Contains("INHUnitOfWork"));
config.Lifecycle.EjectAll();
config.Lifecycle = StructureMap.Pipeline.Lifecycles.GetLifecycle(InstanceScope.HttpContext);
but if I will make it work in one direction it will probably work in both.
Is it possible to replace the initial InstanceScope permanently at runtime? How should this be implemented?
Also, do you think this a good way to obtain a long conversation or there is a better / simpler way to do it with StructureMap & NHibernate?

Take a look at Ayende's detailed explanation on how to enable long running conversations and UnitOfWork:
http://ayende.com/Wiki/Default.aspx?Page=HttpModules&AspxAutoDetectCookieSupport=1
I would recommend creating a UnitOfWorkApplication module and make it responsible for creating a UnitOfWork instance and adding it to the container before your code executes (before the request is processed, like in the example). This way you have more flexibility and control over how unit of work is created.

It sounds slightly strange to me what you are trying to do. Routes I'd try would be
Configure a named instance in StructureMap that also implements said interface but is scoped differently. You can inject different dependencies for different interface consumer, maybe that helps?
Write your own CacheInterceptor that effectively implements your specific lifecycle.
The latter is done e.g. here for WCF lifecycle: http://blogs.rpionline.com/post/2009/02/How-to-use-NHibernate-and-StructureMap-in-a-WCF-application.aspx

Related

Autofac: register component as different services using different constructors

I would like to register a singleton component for multiple services and define which constructor to use, depending on which service was used during the resolve call.
I tried this:
_builder.RegisterType<TComponent>()
.As<IService1>()
.FindConstructorsWith(ConstructorFinder1)
.SingleInstance();
_builder.RegisterType<TComponent>()
.As<IService2>()
.FindConstructorsWith(ConstructorFinder2)
.SingleInstance();
But this leads to two different "singleton" instances, depending on which service was used.
So I tried:
_builder.RegisterType<TComponent>()
.As<IService1>()
.FindConstructorsWith(ConstructorFinder1)
.As<IService2>()
.FindConstructorsWith(ConstructorFinder2)
.SingleInstance();
This solves the singleton issue, but sadly the second FindConstructorsWith call overrides the first call, i.e. for both services ConstructorFinder2 is used.
I had assumed (hoped) that the ConstructorFinders would be stored with respect to the service, but apparently this is not the case.
Is what I'm trying to achieve conceptually wrong, does Autofac not support it or am I simply missing something?
EDIT:
Once again thanks to Travis for his great response. Apparently I left out a few details that made things confusing. Let me add some now.
This question was actually a kind of follow-up to How to determine which constructor Autofac uses when resolving (where Travis also helped me along). So the issue comes up when deserializing and it affects many different objects.
I get the arguments about composition, seperation of concerns and how having several ctors is often considered a code smell, but in the context of deserialization (at least for the app I'm currently developing) it is extremely useful to be able to create instances differently, depending on if they are newly built or deserialized from a project file. Several members that need to be initialized when building a new instance do not have to be initialized when deserializing (because their values would be overridden during deserialization anyway). It would mean extra performance costs and (and, in this case) cause other issues regarding the throw-away-initializations.
After spending days trying to find a solution (with complications also coming from the Newtonsoft Json side) I've decided to discontinue Autofac and implement our own IOC container. For general purposes it cannot (obviously!) compete with Autofac in any way, but since we were really only using a small subset of Autofac's great features, I felt we could try to roll our own. It took me a lot less than the days I've spent on trying to wrap my head around a monolithic black box. Yes, Autofac is open source, but stepping through the code no walk in the park.
First tests are very promising and it feels good to regain full control of such a vital component of the application.
Again, the reason for leaving Autofac was that it is not (feasibly) possible to define how a singleton component is constructed depending on the service it was constructed for. And from a general structure/concept point-of-view I understand that it makes sense to strictly seperate the service and the construction-how-tos. But during deserializing things are different, I believe. And, now that I'm independent of Autofac, I may decide to alter the mechanisms so they fit into the overall concept in a more straight-forward way.
This is sort of a difficult question to answer because it seems you have some underlying goal you're trying to achieve and you have a solution you want to work but perhaps it's the wrong solution and you should ask a [new] question depending on how this response works out for you.
Let me walk this through to see if I can explain why it's hard to answer.
I would like to register a singleton component for multiple services and define which constructor to use, depending on which service was used during the resolve call.
If it's a singleton that means there's one in the whole system, right? It'll be effectively "first in wins." If something resolves it as an IService1 then the constructor associated with that will be called and even if you try resolving it as IService2 later no construction will happen because the singleton was created. The converse is also true - IService2 gets resolved and the constructor path is followed there, then things asking for IService1 will get the singleton and no constructor is called.
That raises a concern:
If you know which thing, for sure, will be resolving first, then why do you need two different constructor selectors?
If you don't know which thing will be resolving first, then are you accounting for the system unpredictability?
I have seen these sorts of questions before and usually what they indicate is one of two things:
You are trying to do some sort of selection or special logic based on context. There's an Autofac FAQ about this that may help. Usually the way around this is to refactor. I'll get back to that in a second.
You are trying to "share registrations" between two different applications. The answer to this is to use Autofac modules and reuse those; but if there are special registrations for each app type, let that happen.
This isn't to say that either of these are what you're asking for, but this is where I've seen such questions. Usually there's some unspoken goal where a solution has been pre-chosen and it's better ask how to solve the goal rather than how to implement a very specific solution. Again, I could be wrong.
On the refactoring note for item 1, above, I can further guess based on the desire for a singleton that there's some sort of resource like a database connection that needs to be shared or is expensive to spin up. Consider splitting the TComponent into three separate classes:
TCommonExpensiveComponent - this is the stuff that is actually expensive to spin up and really does need to be a singleton, but does not differ across IService1 and IService2.
TService1 - implement IService1 with only the required constructor so you don't need a constructor finder. Have it consume TCommonExpensiveComponent.
TService2 - implement IService2 with only the required constructor so you don't need a constructor finder. Have it consume TCommonExpensiveComponent.
The idea being avoid the complexity of registrations, keep the shared/singleton that you want, and still get different constructor usage as needed. You may want to throw in some common base/abstract class, too, that the TService classes can derive from if there's really a lot of common logic.
Is what I'm trying to achieve conceptually wrong, does Autofac not support it or am I simply missing something?
Technically you could do some really crazy stuff in Autofac if you wanted to, like write a custom registration source that waits for someone to query for the IService1 or IService2 registration and then picks a constructor based on that, dynamically serving the registration as needed. But, truly, don't even start down this road.
Instead, it would be good to clarify what the problem is that you're trying to solve and how you plan on working around the challenges listed above if my response here doesn't help. Do that in a brand new question that goes into more detail about your challenge and what you've tried. This not being a forum, having a conversation to try and weed out additional help given the current question really isn't feasible. Plus, taking a second to step back and maybe reframe the question sounds like it might help here.

Injecting a singleton into scopedService

I'm working on adding push notification into my ASP.NET core 2.0.0 webApp. I want to have a notification service that would have a badgeCount member which I would update when I send out notifications or when I mark something as read.
I wanted to make this a singleton, but it seems like I can't use dependency injection for singletons. I need access to my dbContext and maybe some other Identity /or Entity services later.
Would it make sense for me to make my notifcation service a scopedService instead of a singleton so that I can use DI? Then have a notificationBadge singleton that I would inject into my scopedService so I can maintain it?
I'm doing this so that I don't have to calculate the badge count each time (involves using queries)
EDIT: Actually, after writing this I realized that singletons are probably only instantiated once on server startup and not per user. So my initial approach wouldn't work even if I could use DI. I'd probably have to add a field on my user class that extends the IdentityUser then right? Or is there a way around this so that I don't have to update/save this to any db record?
Understanding DI
So to try and cover your question DI is certainly what you want in terms of most things inside your application and website. It can do singletons, as well as scoped and transcients (new copy every time).
In order to really understand DI and specifically the .Net Core implenentation I actually make use of the DI from .Net Core in a stand-alone .Net Standard open source library so you can see how it is done.
Video explaining the DI and showing me make and use the DI outside of ASP.Net Core scene: https://www.youtube.com/watch?v=PrCoBaQH_aI
Source code: https://github.com/angelsix/dna-framework
This should answer your question regarding how to access the DbContext if you do not understand it already from the video above: https://www.youtube.com/watch?v=JrmtZeJyLgg
Scoped/Transcient vs Singleton
What you have to remember when it comes to whether or not to use a singleton instance is singletons are always in-memory, so you should always consider and try to make things scoped or transcient to save memory, if the creation of that service is not intense or slow. So it is basically a trade off between RAM usage vs speed on some generate grounds.
If you then have specific types of service the decision becomes a different one. For example for DbContext objects you can think of them like a "live, in-memory database query/proxy" and so just like SQL queries you want to create them, execute them and be done with them. That is why they are made scoped, so that when a controller is created (per request) a new DbContext is created, injected, used by an action and then destroyed.
I guess the simple answer is it doesn't usually matter too much and most applications won't have any major concern or issues but you do have to remember singletons stay in-memory for the lifecycle of your application or the app domain if you are in a rare multi-domain setup.
Notification Count
So the main question is really about badges. There are many things involved in this process and setup, and so I will limit my answer to the presumption that you are talking about a client logged into a website and you are providing the website UI, and want to show the badge count for, and that you are not on about for example some Android/iOS app or desktop application.
In terms of generating the badge count it would be a combination of all unread messages or items in your database for the user. I would do this calculation on request from the user visiting a page (So in an Action and returned to the view via Razer or ViewBag for example) that needs that information, or from requesting it via Ajax if you are using a more responsive/Ajax style site.
That again I presume is not an issue and I state it just for completeness and presumptions.
So the issue you are asking about is basically that every time the page changes or the badge count is re-requested you are concerned about the time in getting that information from the database, correct?
Personally I would not bother trying to "cache" this outside of the database, as it is a fast changing thing and you will likely have more hit trying to keep the cache in-sync than just calling the database.
Instead if you are concerned the query will be intensive to work out the badge count, I would instead every time any addition to the database of an unread/new item, or a marking of an item as read is done, you do a "SetUnreadCount" call that calculates and writes that value as a single integer to the database so your call to get the unread count is a Scalar call to the database and SUPER quick.

C# Dependency Injection with Unity, a unit of work, a database and the ability to change database at runtime

So I am wrestling with this for quite some time now, but I can't seem to figure it out.
At first I had a datalayer in my solution. This layer is for the communication between the business and the database. It had a generic repository and context objects so it is easy to retrieve and send data from and to the database with EntityFrameWork 6. This all worked very good... but...
Now I notice that in my application (WebAPI 2) I need to change database at runtime. This is really hard to do. It should follow this path:
An external application does a call to my API. In the header of the request is set which database should be used (an Id, or a logic name or whatever, not important now). Before an action is executed some code should read this header-item and set the new connection to the repositories.
This is how I register the repositories for Unity:
container.RegisterType<IContexts.ILanguageCodes<LanguageCode>, Data.LanguageCodes>();
container.RegisterType<IContexts.ISecurityRoles<SecurityRole>, Data.SecurityRoles>();
To show you everything what the implementations of these interfaces are is very much.
To change the connection to an other database I have to change the DBContext, which I know where to find, but the code doesn't. So I started Googling.
Then I found this article: http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/. I read it and all the stuff that is not good is in my project. I was like: Okay, lets start over on the datalayer.
THen I found this article: https://www.danylkoweb.com/Blog/a-better-entity-framework-unit-of-work-pattern-DD. I followed this and came pretty far. But got stuck on the part where the request comes in.
So basicly I am looking for this:
A way to change the connection to an other database at runtime with dependency injection, so I don't have to change the connection everywhere. In the end; the idea of DI is that you don't know where the implementation is, so in this case you don't know where all the connections are.
Does anybody have an example found on the internet I could use to try? Or maybe a good, small example I can focus on?
Long story, I hoped I could make it smaller. I hope someone can help me with this.
Thanks
When I need to support scenarios like this I have one "provisioning" or "configuration" database which holds the connectionstring for each customer/user/whatever. This is separate from the databases which map to the data my application needs.
Whenever the requests comes in you can configure your IOC container with the correct connectionstring, altough I don't know if unity supports this scenario, I know AutoFac / Ninject and most other containers allow changing the container.

Is this an abuse of dependency injection? (when are dependencies not dependencies)

We have a multi-tenant web application in which a many pages operate per-tenant. As a result many of our interfaces look like this
interface ISprocketDeployer
{
void DeploySprocket(int tenantId);
}
It occurred to me that it might be better to simplify these interfaces to be unaware of the tenantId. The pages would also then be unaware of the tenantId, like so
[Inject] // Ninject
public ISprocketDeployer SprocketDeployer { get; set; }
private void _button_OnClick(object sender, EventArgs e)
{
SprocketDeployer.DeploySprocket();
}
The dependency injection framework would then inject the tenant ID as a dependency by looking at the currently authenticated user. Is this a good idea or just an abuse of dependency injection?
It further occurred to me that many implementations also take additional dependencies just for looking up details about the tenant, and that I could reduce the number of dependencies further by just injecting in that detail directly, for example
class SprocketDeployer
{
public SprocketDeployer(ITenantRepository tenantRepository)
{
_tenantRepository = tenantRepository;
}
void DeploySprocket(int tenantId)
{
var tenantName = _tenantRepository.GetTenant(tenantId).Name;
// Do stuff with tenantName
}
}
Would become
class SprocketDeployer
{
public SprocketDeployer(Tenant tenant)
{
_tenant = tenant;
}
void DeploySprocket()
{
var tenantName = _tenant.Name;
// Do stuff with tenantName
}
}
I then realised that I could also inject in other "dependencies", such as details about the currently logged in user in the same way.
At that point I become unsure. While it seemed like a fantastic idea at first I realised that I wasn't sure when to stop adding extra "dependencies". How do I decide what should be a dependency and what should be a parameter?
I would stop short of calling it abuse, but that said:
The general use case of dependency injection (via a container) is to inject pure services that do not directly represent state. One of the immediate problems is informing the container of which instance of your object it should be injecting at run-time. If your SprocketDeployer requires a Tenant, and your system includes many Tenants, how does the container figure out which tenant to supply at runtime?
If you want to avoid passing Tenant around, consider using Thread Local Storage (TLS). However, there will still be some point in the pipeline where the Tenant needs to be added to TLS.
Edit
From your comment:
I solve the problem of figuring out which tenant to supply at runtime
in Ninject by binding the type to a method which examines
HttpContext.Current and using InRequestScope. It works fine, but I've
not seen anything to indicate that this is (or isn't) a recommended
practice.
If I understand you correctly, that sounds like a factory of sorts? If that's the case, I see nothing wrong with it.
A minor nitpick might be: it's nice to be able to not have to be concerned about how your services are scoped. When they are truly stateless services, you can view them as pure swappable components that have no side effects based on container configuration.
As with Phil, I would not call this dependency injection abuse, though it does feel a bit odd.
You have at least a few options. I'll detail a couple that seem the best from the detail you've provided, though these may have been what you were referring to when you said 'I then realised that I could also inject in other "dependencies", such as details about the currently logged in user in the same way.'
Option 1: Abstract tenant identification to a factory
It may make perfect sense to have an abstraction that represents the current tenant. This abstraction is a factory, but I prefer the term "provider" because factory connotes creation whereas a provider may simply retrieve an existing object (Note: I realize Microsoft introduced a provider pattern but that's not what I'm referring to). In this context you're not injecting data, instead you're injecting a service. I'd probably call it ICurrentTenantProvider. The implementation is frequently context specific. Right now, for example, it would come from your HttpContext object. But, you could decide a specific customer needed their own server and then inject an ICurrentTenantProvider that would retrieve it from your web.config file.
Option 2: Hide multitenancy entirely
Unless you ever have to do different things based on the tenant[1], it may be better to hide the multitenancy entirely. In this case you'd inject classes, that I'm going to call providers, that are context aware and the result of whose function calls would be based on the current tenant. For example, you might have an ICssProvider and an IImageProvider. These providers alone would be aware that the application supported multitenancy. They may use another abstraction such as the ICurrentTenantProvider referenced above or may use the HttpContxt directly. Regardless of the implementation, they would return context specific to the tenant.
In both cases, I'd recommend injecting a service instead of data. The service provides an abstraction layer and allows you to inject an implementation that's appropriately context aware.
Making the Decision
How do I decide what should be a dependency and what should be a parameter?
I generally only ever inject services and avoid injecting things like value objects. To decide you might ask yourself some questions:
Would it make sense to register this object type (e.g., int tenantId) in the IoC container?
Is this object/type consistent for the standard lifetime of the application (e.g., instance per http request), or does it change?
Will most objects end up dependent on this particular object/type?
Would this object need to be passed around a lot if made a parameter?
For (1), it doesn't make sense to inject value objects. For (2), if it is consistent, as the tenant would be, it may be better to inject a service that's aware of the tenant. If yes to (3), it may indicate a missing abstraction. If yes to (4) you may again be missing an abstraction.
In the vein of (3) and (4) and depending on the details of the application, I could see ICurrentTenantProvider being injected in a lot of places, which may indicate it's a little low level. At that point the ICssProvider or similar abstractions may be useful.
[1] - If you inject data, like an int, you're forced to query and you may end up in a situation where you'd want to replace conditional with polymorphism.
10/14/15 UPDATE BEGIN
A little over three months later I've had a bit of a change of heart on the specific situation I mentioned running into with this approach.
I had mentioned that for a long time now I've also regularly injected the current "identity" (tenantAccount, user, etc.) wherever it was necessary. But, that I had ran into a situation where I needed the ability to temporarily change that identity for just a portion of the code to be executed (within the same execution thread).
Initially, a clean solution to this situation wasn't obvious to me.
I'm glad to say that in the end I did eventually come up with a viable solution - and it has been happily churning away for some time now.
It will take some time to put together an actual code sample (it's currently implemented in a proprietary system) but in the meantime here is at least a high level conceptual overview.
Note: Name the interfaces, classes, methods, etc. whatever you like - even combine things if that makes sense for you. It's just the overall concepts that are important.
First, we define an IIdentityService, exposing a GetIdenity(). This becomes the de facto dependency for getting the current identity anywhere we need it (repos, services, etc. everything uses this).
The IIdentityService implementation takes a dependency on an IIdentityServiceOrchestrator.
In my system the IIdentityServiceOrchestrator implmentation makes use mutliple IIdentityResolvers (of which only two are actually applicable to this discussion: authenticatedIdentityResolver, and manualIdentityResolver). IIdentityServiceOrchestrator exposes a .Mode property to set the active IIdentityResolver (by default this is set to 'authenticated' in my system).
Now, you could just stop there and inject the IIdentityServiceOrchestrator anywhere you needed to set the identity. But, then you'd be responsible for managing the entire process of setting and rolling back the temporary identity (setting the mode, and also backing up and restoring the identity details if it was already in manual mode, etc.).
So, the next step is to introduce an IIdentityServiceOchestratorTemporaryModeSwitcher. Yes, I know the name is long - Name it what you want. ;) This exposes two methods: SetTemporaryIdentity() and Rollback(). SetTemporaryIdentiy() is overloaded so you can set via mode or manual identity. The implementation takes a dependency on the IIdentityServiceOrchestrator and manages all the details of backing up the current existing identity details, setting the new mode/details, and rolling back the details.
Now, again you could just stop there and inject IIdentityServiceOchestratorTemporaryModeSwitcher anywhere you'd need to set the temporary identity. But, then you'd be forced to .SetTemporaryIdentity() in one place and .Rollback() in another and in practice this can get messy if it's not necessary.
So, now we finally introduce the final pieces of the puzzle: TemporaryIdentityContext and ITemporaryIdentityContextFactory.
TemporaryIdentityContext Implements IDisposable and takes a dependency on both the IIdentityServiceOchestratorTemporaryModeSwitcher and an Identity / Mode set via an overloaded constructor. In the ctor we use the IIdentityServiceOchestratorTemporaryModeSwitcher.SetTemporaryIdentity() to set the temporary identity and on dispose we call into IIdentityServiceOchestratorTemporaryModeSwitcher.Rollback to clean things up.
Now, where we need to set the identity we inject the ITemporaryIdentityContextFactory which exposes a .Create() (again overloaded for identity / mode) and this is how we procure our temporary identity contexts. The returned temporaryIdentityContext object itself isn't really touched it just exists to control the lifetime of the temporary identity.
Example flow:
// Original Identity
Using (_TemporaryIdentityContextFactory.Create(manualIdentity)) {
// Temp Identity Now in place
DoSomeStuff();
}
// Back to original Identity again..
That's pretty much it conceptually; obviously a LOT of the details have been left out.
There's also the matter of IOC lifetime that should be discussed. In its purest form as discussed here, generally each of the componenets (IIdentityService, IIdentityServiceOrchestrator, ITemporaryIdentityContextFactory) could be set to a 'PerRequest' lifetime. However, it could get funky if you happen to be spawing multiple threads from a single request... in which case you'd likely want to go with a 'perthread', etc. lifetime to ensure there was no thread crosstalk on the injections.
Ok, hope that actually helps someone (and didn't come across as completely convoluted, lol). I'll post a code sample that should clear things up further as I have time.
10/14/15 UPDATE END
Just wanted to chime in and say you're not alone in this practice. I've got a couple multi-tenant apps in the wild that inject the tenant information where it's needed in the same manner.
However, I have more recently ran into an issue where doing this has caused me quite a bit of grief.
Just for the sake of example lets say you have the following (very linear) dependency graph:
ISomeService -> IDep2 -> IDep3 -> ISomeRepository -> ITenentInfoProvider
So, ISomeService depends IDep2, which depenends on IDep3... so on and so on until way out in some leaf ITenentInfoProvider is injected.
So, what's the problem? Well, what if in ISomeService you need to act on another tenant than the one you're currently logged in as? How do you get a different set of TenantInfo injected into ISomeRepository?
Well, some IOC containers DO have context-based conditional support (Ninject's "WhenInjectedInto", "WhenAnyAnchestorNamed" bindings for example). So, in simpler cases you could manage something hacky with those.
But what if in ISomeService you need to initiate two operations, each against a different tenant? The above solutions will fail without the introduction of multiple marker interfaces, etc. Changing your code to this extent for the sake of dependency injection just smells bad on multiple levels.
Now, I did come up with a container based solution, but I don't like it.
You can introduce an ITenantInfoResolverStratagy and have an implementation for each "way" of resolving the TenantInfo (AuthenticationBasedTenantInfoResolverStratagy, UserProvidedTenantInfoResolverStratagy, etc.).
Next you introduce a CurrentTenantInfoResolverStratagy (registered with the container as PerRequestLifeTime so it's a singlton for the life of your call, etc.). This can be injected anywhere you need to set the strategy that will be used by downstream clients. So, in our example we inject it into ISomeService, we set the strategy to "UserProvided" (feeding it a TenantId, etc.) and now, down the chain, when ISomeRepository asks ITenentInfoProvider for the TenantInfo, ITenentInfoProvider turns around gets it from an injected CurrentTenantInfoResolverStratagy.
Back in ISomeService, the CurrentTenantInfoResolverStratagy could be changed multiple times as needed.
So, why don't I like this?
To me, this is really just an overly complicated global variable. And in my mind just about all the problems associated globals apply here (unexpected behavior due to it being mutable by anyone at any time, concurrency issues, etc. etc. etc.).
The problem this whole thing sets out to solve (mostly just not having to pass the tenantId / tenantInfo around as a parameter) is probably just not worth the inherent issues that come with it.
So what's a better solution? Well there probably is some elegant thing that I'm just not thinking of (maybe some Chain Of Command implemenation?).
But, really I don't know.
It may not be elegant but passing a TenantId / TenantInfo around as a parameter in any tenant related method calls would definitely avoid this whole debacle.
If anyone else has better ideas please by all means chime in.

Intercept ALL services

We have small lifetime scopes in our applications. It would be interesting to be able to intercept all services registered in autofac. By doing so we can see exactly which path the code takes for every lifetime scope and which method arguments are used. Not really usable for production but when really great for debugging/diagnostics/refactoring as you ge the whole picture and not just unit level.
But AFAIK it's only possible to register an interceptor for each single registration?
Nothing like this is supported out of the box with the Autofac.Extras.DynamicProxy2 library. You could potentially implement something like a module that handles OnActivating for every component using code similar to the stuff in Autofac.Extras.DynamicProxy2, but you'll run into trouble like...
Do you want class interceptors or interface interceptors? The type of service being resolved vs. the limit type of the component backing it will influence what kind of dynamic proxy you want to make. I believe the current A.E.D2 code only generates interception for either/or - not every interface a class implements, etc.
Do you use WCF client proxies? Client proxies are an interesting beast of their own so you have to special-case them. You'll see that in A.E.D2.
Generally problems like this get solved by aspect-oriented programming solutions (e.g., PostSharp) or profilers (e.g., ANTS)... or a combination of both. You might want to look into those solutions if you have the ability.
For an example of what sort of module implementation I'm talking about, check out the log4net integration page on the Autofac wiki. That shows how to handle OnPreparing for every component in the system. You can do the same thing, but handle OnActivating instead and use the sample on the Lifetime Events wiki page to show you how to swap one resolved thing for another (swap the real object for the generated proxy).

Categories