Closed Ergamon closed 3 years ago
the unregistered type event handler is now called for a lot of types for which my code is not prepared to handle.
Can you elaborate on this? Unregistered type resolution only triggers on unregistered types, so what unregistered types get resolved and why is your code not prepared for this?
The old system was build with a self written (very bad) container system. I am more and more migrating everything to SimpleInjector, but as a fallback mechanism I call the old one.
So let´s assume we have a class with 2 methods: bool CanResolve(Type type) and Type Resolve(Type type)
Now I create a new WebAPI project in VS and copy the slightly modified code from your page at the right place in the Global.asax.cs file:
// Create the container as usual.
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
// Register your types, for instance using the scoped lifestyle:
container.ResolveUnregisteredType += (s, e) =>
{
var type = e.UnregisteredServiceType;
if (LegacyResolver.CanResolve(type))
{
e.Register(() => LegacyResolver.Resolve(type));
}
};
// This is an extension method from the integration package.
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
As you can see there are no registrations at all.
When I start the web site the ResolveUnregisteredType
event handler is called with a type named ModelMetadataProvider
and there is where my problem lies. The legacy resolver thinks that he can resolve this type, but actually he cant (and from my perspective he shall not).
So my question is how do I suppress this call or if this is not possible how do I extend this CanResolve
method to identify such types?
(There are more calls to the event handler, not only the ModelMetadataProvider
, but this is the first call already crashing my demo app)
What's happening here is that ASP.NET Web API calls the IDependencyResolver
abstraction on almost all its own types, in order to let the application container compose them. In case the custom IDependencyResolver
returns null
, Web API will create the type itself. This means that ModelMetadataProvider
is just the first, of many requests Web API will be making to IDependencyResolver
.
When a request comes in, the SimpleInjectorWebApiDependencyResolver
will detect the ModelMetadataProvider
isn't registered in Simple Injector and will return null
(by calling Container.GetService(Type)
). So far so good, but, even a call to GetService
will trigger unregistered type resolution when the registration does not exist.
There doesn't exist a specific mechanism in Simple Injector to configure when ResolveUnregisteredType
should go off, and when not. This means that you will have to implement this check inside your `ResolveUnregisteredType
event.
Probably a good way to do so if by filtering out types that come from the System.Web.Http
namespace; likely all requested types will be defined in System.Web.Http
or a sub namespace.
Thx for the confirmation, that is basically what I did. I extended my CanResolve method by checking the namespace of the type.
So my question was basically, if there is a better solution.
Obviously there isn´t.
Thx for your time and help
So my question was basically, if there is a better solution.
No, I'm afraid there isn't.
I am still struggling with our legacy application.
In a library I have build a more or less generic base composition root. We have different types of applications using this composition root extending it with more specific registrations. Sadly due to the nature of the old code I have sometimes to rely on resolving unregistered types, but regardless of the uglyness it works now for quite a while.
In the process of creating new applications, we want to build an REST API around the old application.
So today I created a new web application following your instructions on using SimpleInjector with Web API.
So basically the only part that is different is the part of registering my own types. There I basically do everything my base composition root does.
Sadly it does not work, cause the unregistered type event handler is now called for a lot of types for which my code is not prepared to handle.
Is my approach wrong? Is there any good way to differ between types queried by the web api code and my application code? (As a quick hack I changed my unregistered type handler to look for System.Web in the full type name and everything seems to work. But this feels more or less wrong)