How does ninject work at a high level, how does it intercept object instantiation? - asp.net

At a high level, how do these dep. injection frameworks work?
I can understand if you always instantiate an object via a custom factory like:
IUser user = DepInjector.Get<User>();
I'm guessing what happens is, wherever you defined the mappings, it will look at the type you want and try and find a match, if found, it will via reflection instantiate the type.
Are there dep. inj. frameworks that would work like:
IUser user = new User();
If so, how would it get the correct user, where is it hooking into the CLR to do this? In case of an asp.net website, is it any different?

If you want to know how Ninject works then the obvious place to start would be reading How Injection Works on their official wiki. It does use reflection but it now also uses dynamic methods:
"By default, the StandardKernel will
create dynamic methods (via
System.Reflection.Emit.DynamicMethod)
that can be used to inject values into
the different injection targets. These
dynamic methods are then triggered via
delegate calls."
As for you second example, I don't believe there are any DI frameworks that would do what you ask. However, constructor injection tends to be most common way of implementing IoC, so that when a class is constructed it knows what type to bind to via some configuration binding. So in your example IUser would be mapped to concrete User in config bindings so that any consuming class that has an IUser parameter as part of its constructor would get the correct User type passed in.

AFAIK there's no way to "hook into" object instantiation with the CLR. The only way to use DI in the second case would be to employ an assembly rewriter (i.e. a postprocessor similar to PostSharp) to replace the call to new with a call to the DI factory method (i.e. GetUser) in the compiled code.

Related

How to provide capability like OnActivate (in Autofac) in Mvx.IoCProvider.Register

Autofac provides the OnActivated() method, which provides the capability to run any action after constructing a registered type.
Is possible to use a similar method in MvvmCross? Do you have any ideas to provide the same functionality?
It usually pays to understand the fundamentals of Dependency Injection (DI) instead of relying on particular DI Container features. Ask yourself the question: If I didn't have a DI Container, then how would I solve my problem?
Ironically, it turns out that things are usually much simpler with Pure DI.
If you didn't have a DI Container, then how would you run an action after construction of an object?
The easiest solution is to provide a factory that creates and initialises the object. Assuming the same API and requirements as the Autofac documentation implies, you could do this:
public static Dependency2 CreateDependency2(ITestOutputHelper output, Dependency1 dependency)
{
var d2 = new Dependency2(ITestOutputHelper output, Dependency1 dependency);
d2.Initialize();
return d2;
}
If you still must use another DI Container, most of them enable you to register a factory like the above against the type. I don't know how MvvmCross works, but I'd be surprised if this wasn't possible. If it isn't, you can implement an Adapter over your actual dependency. The Adapter would take care of running the action on the adapted object.
FWIW, if an object isn't in a valid state before you've run some action on it, then encapsulation is broken. The fundamental characteristic of encapsulation is that objects protect their invariants so that they can never be in invalid states. If possible, consider a better API design.

Dependency injection using PRISM Xamarin Forms doesn't work

I have a problem with dependency injection in my project. I use PRISM framework in my project and I chose Ioc container when create it. Link -> https://github.com/blackpantific/InstagroomEX
In my app.xaml file I associate the class and interface
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation();
containerRegistry.RegisterForNavigation<WelcomeView, WelcomeViewModel>();
containerRegistry.RegisterForNavigation<RegistrationView, RegistrationViewModel>();
containerRegistry.RegisterForNavigation<LoginView, LoginViewModel>();
//regestering
containerRegistry.RegisterSingleton<IValidationService, ValidationService>();
}
But my page after initializing() doesn't appear at the screen. This is ViewModel constructor
public RegistrationViewModel(INavigationService navigationService, IUserDataService userDataService,
IValidationService validationService) :
base(navigationService)
{
_userDataService = userDataService;
_validationService = validationService;
}
Something wrong here. When I pass to the RegistrationViewModel() constructor another parameters besides INavigationService navigationService the RegistrationView page doesn't not displayed. What am I doing wrong?
Assuming that WelcomePage is displayed correctly and RegistrationPage is not, I think that Andres Castro is correct: Prism tries to resolve the IUserDataService which is not possible. In the debug output you should see a message that IUserDataService cannot be resolved.
(Note: The following is based on my experiences with Prism and Unity. This might hold for other Dependency Injection frameworks, but it's possible that other frameworks behave differently.)
Prism relies on a Dependency Injection (DI) framework, for example Microsofts Unity application block. What happens when you try to navigate to RegistrationPage is, that Prism (if you are using ViewModelLocator.AutowireViewModel="True") tries to determine the type of the viewmodel (by convention) and asks the underlying DI framework to resolve this type (i.e. create an instance). For each of the required constructors parameters of this type, then again the DI framework tries to resolve them. If the parameters require concrete types it will then try to resolve those. If the parametery require interface (or abstract) types, the DI framework will look at its registrations and if the types have been registered create instances according to this registrations (which in turn might involve resolving other types).
If - however - the parameter requires an interface type which has not been registered, the DI framework does not know how to handle the situation. It coulld of course assume null, but this might lead to errors that might be way harder to track down, hence it will throw an exception (which is swallowed and Logged by Prism).
Now how can you handle the situation?
You'll need to tell the DI framework how to resolve IUserDataInterface. Since RegistrationPageViewModel does not actually use it, you could register null
containerRegistry.RegisterInstance<IValidationService>(null);
Could be irritating later, though. I'd rather remove the dependency of RegistrationPageViewModel to IUserDataService altogether - for now and add it later when it's actually used - or create a mock/stub that implements IUserDataService and is used as long there is no real implementation. This would be registered with the DI framework as you did with IValidationService.

What is the point of #WebInitParam?

#WebInitParam is an annotation that goes at class level.
It defines initialization parameters for the servlet.
I would like to know, what is the difference between doing this and using static variables, and why do it the #WebInitParam way rather than using statics?
What does defining k/v pairs as #WebInitParams allow you to do that you couldn't do if you declared static variables instead?
I have looked and all I can find is a million people saying how to define #WebInitParams. Well yes that's the easy bit. It's what I can do with that that is really what is of interest.
Thanks very much.
From a "raison d'etre" perspective, the annotation exists as a better design and architecture alternative to just peppering a class with static fields. #WebInitParam is a self-documenting approach to the initialization parameters a servlet or filter class needs, available via web.xml as well. It serves this purpose for the end developers as well as the JavaEE platform as a whole.
Think about it this way: in a vanilla project, you have the option of hardcoding a bunch of parameters in the class as static fields, or defining the same parameters in a property file. Which would you pick? Under what circumstances?
From a purely functional angle, apart from the function of using the annotation to override defaults set in web.xml, one other major reason is that you will sometimes need to get a hold of those initialization parameters from another component in your application. Using the annotation essentially increases the visibility of the parameter. In JSF for example, the API allows you to retrieve FacesServlet initialization parameters with:
//get all the parameters
FacesContext.getCurrentInstance().getExternalContext().getInitParameterMap()
//get a specific parameter
FacesContext.getCurrentInstance().getExternalContext().getInitParameter("aParameter");
In JSF-2.3 , it gets even more convenient with the following CDI-enabled injection:
#InitParameterMap Map<String,String> servletParameterMap;
Bear in mind that because it's CDI, it means this facility is available throughout the JavaEE platform, not just in web applications/JSF.
It's going to be a hassle to retrieve init parameters if the only mechanism available is a static field in the servlet class - you'll need to obtain an instance of the filter or servlet to get the static fields in it.
Separately, one could make the argument that maybe one should favour context-params over servlet-params because then, you get even more flexibility that isn't tied to any given servlet. That's a separate matter entirely :)

Asp.net MVC RouteBase and IoC

I am creating a custom route by subclassing RouteBase. I have a dependency in there that I'd like to wire up with IoC. The method GetRouteData just takes HttpContext, but I want to add in my unit of work as well....somehow.
I am using StructureMap, but info on how you would do this with any IoC framework would be helpful.
Well, here is our solution. Many little details may be omitted but overall idea is here. This answer may be a kind of offtop to original question but it describes the general solution to the problem.
I'll try to explain the part that is responsible for plain custom HTML-pages that are created by users at runtime and therefore can't have their own Controller/Action. So the routes should be either somehow built at runtime or be "catch-all" with custom IRouteConstraint.
First of all, lets state some facts and requirements.
We have some data and some metadata about our pages stored in DB;
We don't want to generate a (hypothetically) whole million of routes for all of existing pages beforehand (i.e. on Application startup) because something can change during application and we don't want to tackle with pushing the changes to global RouteCollection;
So we do it this way:
1. PageController
Yes, special controller that is responsible for all our content pages. And there is the only action that is Display(int id) (actually we have a special ViewModel as param but I used an int id for simplicity.
The page with all its data is resolved by ID inside that Display() method. The method itself returns either ViewResult (strongly typed after PageViewModel) or NotFoundResult in case when page is not found.
2. Custom IRouteConstraint
We have to somewhere define if the URL user actually requested refers to one of our custom pages. For this we have a special IsPageConstraint that implements IRouteConstraint interface. In the Match() method of our constraint we just call our PageRepository to check whether there is a page that match our requested URL. We have our PageRepository injected by StructureMap. If we find the page then we add that "id" parameter (with the value) to the RouteData dictionary and it is automatically bound to PageController.Display(int id) by DefaultModelBinder.
But we need a RouteData parameter to check. Where we get that? Here comes...
3. Route mapping with "catch-all" parameter
Important note: this route is defined in the very end of route mappings list because it is very general, not specific. We check all our explicitly defined routes first and then check for a Page (that is easily changeable if needed).
We simply map our route like this:
routes.MapRoute("ContentPages",
"{*pagePath}",
new { controller = "Page", action = "Display" }
new { pagePath = new DependencyRouteConstraint<IsPageConstraint>() });
Stop! What is that DependencyRouteConstraint thing appeared in mapping? Well, thats what does the trick.
4. DependencyRouteConstraint<TConstraint> class
This is just another generic implementation of IRouteConstraint which takes the "real" IRouteConstraint (IsPageConstraint) and resolves it (the given TConstraint) only when Match() method called. It uses dependency injection so our IsPageConstraint instance has all actual dependencies injected!
Our DependencyRouteConstraint then just calls the dependentConstraint.Match() providing all the parameters thus just delegating actual "matching" to the "real" IRouteConstraint.
Note: this class actually has the dependency on ServiceLocator.
Summary
That way we have:
Our Route clear and clean;
The only class that has a dependency on Service Locator is DependencyRouteConstraint;
Any custom IRouteConstraint uses dependency injection whenever needed;
???
PROFIT!
Hope this helps.
So, the problem is:
Route must be defined beforehand, during Application startup
Route's responsibility is to map the incoming URL pattern to the right Controller/Action to perform some task on request. And visa versa - to generate links using that mapping data. Period. Everything else is "Single Responsibility Principle" violation which actually led to your problem.
But UoW dependencies (like NHibernate ISession, or EF ObjectContext) must be resolved at runtime.
And that is why I don't see the children of RouteBase class as a good place for some DB work dependency. It makes everything closely coupled and non-scalable. It is actually impossible to perform Dependency Injection.
From now (I guess there is some kind of already working system) you actually have just one more or less viable option that is:
To use Service Locator pattern: resolve your UoW instance right inside the GetRouteData method (use CommonServiceLocator backed by StructureMap IContainer). That is simple but not really nice thing because this way you get the dependency on static Service Locator itself in your Route.
With CSL you have to just call inside GetRouteData:
var uow = ServiceLocator.Current.GetService<IUnitOfWork>();
or with just StructureMap (without CSL facade):
var uow = ObjectFactory.GetInstance<IUnitOfWork>();
and you're done. Quick and dirty. And the keyword is "dirty" actually :)
Sure, there is much more flexible solution but it needs a few architectural changes. If you provide more details on exactly what data you get in your routes I can try to explain how we solved our Pages routing problem (using DI and custom IRouteConstraint).

how can i use structure map asp.net 3.5

I am new to the structure map but i want to use it in my asp.net site for dependency injection
can any one suggest me simple example to use structure map for the dependency injection
you will need to do something like this:-
StructureMapConfiguration
.ForRequestedType<IResourceA>()
.TheDefaultIsConcreteType<ResourceB>()
.CacheBy(InstanceScope.Singleton);
This tells StructureMap to inject ResourceB when there is a request for ResourceA.
Structure Map
You can configure programatically or via configuration file.
Programatical example (there are other ways):
StructureMap.StructureMapConfiguration.ForRequestedType<ISomething>().TheDefaultIsConcreteType<ConcreteSomething>();
then you can get an instance of the configured type using this sort of code:
//The concrete type will be ConcreteSomething
ISomething instance = ObjectFactory.GetInstance<ISomething>();
You can do it in a config file:
<StructureMap MementoStyle="Attribute">
<DefaultInstance PluginType="Blah.ISomething, Blah.SomethingDLL" PluggedType="Blah.Concrete.ConcreteSomething,Blah.ConcreteDLL"/>
</StructureMap>
and in the main method or Global.asax you can set this config by saying:
StructureMap.ObjectFactory.Initialize(x => { x.PullConfigurationFromAppConfig = true; });
and use it the same way as above:
ISomething instance = ObjectFactory.GetInstance<ISomething>();
If the concrete class has a constructor that needs instances injected in it, and you have those configured, the concrete types will get injected by the framework.
There are ways of passing parameters to constructors, dealing with Gereric types, creating named instances that are configured with specific constructor/property values. I use this framework and like it very much.

Resources