public class MyHttpHandler : IHttpHandler
{
public MyHttpHandler() { ... }
public IUnityContainer Container { get; set; }
}
Is there a way to somehow get Container magically be set to a container I setup in global.asax?
Right now I can't find a way of doing it other than using AppDomain.CurrentDomain.GetData("container") as IUnityContainer.
Please let me know if there is a cleaner way of doing this.
First hit on google for asp.net mvc2 unity
http://weblogs.asp.net/shijuvarghese/archive/2010/05/07/dependency-injection-in-asp-net-mvc-nerddinner-app-using-unity-2-0.aspx
There are plenty of articles about MVC and Unity. You basically need to create a custom controller factory (in mvc2). MVC3 got a different solution.
Update
Use the BuildUp method in global.asax.
Sry. that was for existing objects. Why not just Register it and directly after Resolve it?
Singleton pattern may help you)
I would use service location instead.
Related
I have a problem that I don't know how to solve. I have a container which contains different interfaces for different services that I expose with a WebApi. The problem is that I need to get that dependencies inside my controller and I must avoid the use of static. I read about this
http://beletsky.net/2011/10/inside-aspnet-mvc-idependencyresolver.html
http://www.asp.net/web-api/overview/advanced/dependency-injection
In the asp.net I read that I can implement my own IDependencyResolver. Is this madness? because I searched a lot and I only found examples using Unity. If I don't want to use that dependency injector? What it's the best way to achieve this?.
public class MyController: ApiController
{
private InterfaceService m_interfaceService; //This is the dependency I need
public MyController()
{
}
[HttpGet]
[Route("myServices/")]
public List<IServiceCategory> GetServiceObjectsList()
{
return m_interfaceServices.GetObjectsList();
}
}
So you have an pre-existing container/dependency mechanism! You should ask your team why it was a good idea to make something like that instead of using all the good ones out in the .net world.
Nonetheless, from the docs:
http://www.asp.net/web-api/overview/advanced/dependency-injection
Although you could write a complete IDependencyResolver implementation
from scratch, the interface is really designed to act as bridge
between Web API and existing IoC containers.
The Unity example on that page shows what must be done to bridge the gap between Unity DI framework and the web mvc. You just need to do the same thing with your home-rolled one. It's matter of implementing just a few methods. Go for it!
Here is an implementation that meets your requirements:
namespace AdvancedDI.Controllers
{
public class ProductController : ApiController
{
public IFactory iFactory { get; set; }
protected override void Initialize(HttpControllerContext controllerContext)
{
DIAPP.GetContainer(this);
base.Initialize(controllerContext);
}
public IHttpActionResult Get()
{
var response = iFactory.DoWork();
return Ok(response);
}
protected override void Dispose(bool disposing)
{
DIAPP.Dispose(this);
base.Dispose(disposing);
}
}
}
This is one kind of property based injection. It is possible with UnityContainerExtensions. The Initialize method will get called before Get.
Step 1. DIAPP.GetContainer(this) carries the entire productController context.
Step 2. GetContainer receives the IFactory property information from this.
Step 3. Next, you have a chance to receive the unity IBuilderContext for this IFactory.
I've used both Ninject and AutoFac for dependency injection. This is not madness, it's common practice.
I'm experimenting with IoC in my Web App and would like to do things according to best practices. Recently I discovered an IoC framework called DryIoc which is supposed to be small and fast.
I've read through the examples but none seem to point out where I should put the container itself.
Should it reside in the controller? Or in Global.asax? Someplace else maybe? Or perhaps as a static variable in a class?
I'd appreciate if someone would be able to guide me in the right direction, preferrably with some sample code, as I've stalled and don't got a clue on how to continue.
var container = new Container(); // Should obviously NOT be a local variable
container.Register<ISalesAgentRepository, SalesAgentRepository>(Reuse.Singleton);
Usually I do the following:
1 - Create a bootstrapper class
public static class Bootstrapper {
public static Container _container;
public void Bootstrap() {
var container = new Container;
// TODO: Register all types
_container = container;
}
public static T GetInstance<T>() {
return _container.Resolve<T>();
}
}
2 - Call the bootstrap method in the global.asax, in the Application_Start method:
protected void Application_Start() {
Bootstrapper.Bootstrap();
}
And never use the container anywhere directly, you have to hook it somewhere in the MVC lifecycle, and usually the DI package you use can do this for you.
Also note that I've added a GetInstance<T> method to the bootstrapper-class. This method is what makes it possible to use the container directly by requesting instances of types. I've added this method so you know it is possible, but always use constructor-injection if possible.
Actually, you may not need to store container on your side. Here is the DryIoc WebApi Owin sample.
The DryIoc.WebApi extension will store and Dispose the container when it is appropriate in IDependencyResolver implementation.
I am working on an app which uses active directory to retrieve users. Sometimes I need to work on the app but AD is not available. I use a wrapper class to retrieve the AD user. I would like to inject a different class based on the configuration. I was thinking on using an appSetting that would tell me the current configutarion and decide what type to use when injecting. Is it possible to get the current configuration without using a Web.config transform? Is it possible to inject objects using Unity based on Web.config transformations? Can you recommend a better approach?
[UPDATE]
I have a user repository class that loads the users from AD. All I need is to be able to change the implementation of this repository class so that when AD is unavailable I can load the users a different way. This would only be used for development, production would always access AD and retrieve users.
You can use preprocessor directives:
#if DEBUG
// register fake repository
#else
// register AD repository
#endif
Well, Dependency Injection is incredibly powerful, agile, and creates a separation of concerns. The pitfall in your approach will come from validation. You see, with this approach you have to choose a concrete implementation.
So how will you call those two classes?
public class LogToText : ILogger
{
public void LogMessage(string message) { }
}
public class LogToEvent : ILogger
{
public void LogMessage(string message) { }
}
You have these two implementations, but when you pass the interface to:
public class AD
{
public AD(ILogger logger) { }
}
So the question will be do you feel that you can properly validate to choose the proper implementation effectively. Otherwise, Dependency Injection may not work well. We don't entirely know the usage or goal, so our advice may not be truly beneficial. Hopefully you see what I mean, because you'll have to see if you can't test a particular way.
You could use an Abstraction for this:
public interface IPersonService
{
IEnumerable<Person> Find(PersonSearchParameters searchParams);
Person GetByAccountName(string accountName);
[ETC...]
}
Then both your AD and Development implements this interface.
To make things easier, I suggest using StructureMap IoC, so you can easily do this:
x.For<IPersonService>.Use<ActiveDirectoryPersonService>(); //for production
or
x.For<IPersonService>.Use<MockPersonService>(); //for development
When using this you can, for instancce:
public class TestController : Controller
{
IPersonService _service;
public TestController(IPersonService service)
{
_service = service;
}
}
Instead of using an XML file for configuration in this case, I suggest using the Fluent code of Structure Map, it's better when refactoring and to avoid mistyping because it compiles.
StructureMap:
http://structuremap.net
Easy Installable via NuGET
A different approach would be to use the build configuration, read back from the assembly.
var buildConfiguration = typeof(Program).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>()?.Configuration;
if (buildConfiguration == "Debug")
{
// register fake repository
}
else
{
// register AD repository
}
Then it is safer to apply refactorings or automatic code clean up (e.g. ReSharper etc.). Depending on your current configuration, code cleanup can otherwise remove unused usings. What then leads to build issues if an other configuration is used.
I am a little lost as to where I need to look to resolve the error message below.
The history is that I added a new service object to the project and instantiate / inject it when a new section of the site is accessed. (MVC 3 site repository/service architecture).
The error is:
Cannot resolve parameter 'XService pl_xService' of constructor 'Void .ctor(.....
Now this is straight forward enough to understand. The newly added parameter XService can't be resolved...
The error is thrown by Autofac.core.dependency but I am not sure where / how I would register my new object for Autofac.
I understand you have no clue how my project is setup so I'm just looking for greater understanding of what is going on thus enabling me to track down where I need to register my new service object with Autofac etc.
FWIW:
Controller for new section of the site:
public partial class NewSectionController : BaseController
{
private readonly IPL_XService _pl_xService;
#region Constructors
public NewSectionController(IPL_XService pl_xService,....)
{
this._pl_forumService = pl_forumService;
}
.....controller actions, helpers, utilities etc.........
}
Since I am in waters I have not spent much time (if any really) in please let me know of any other code, style, architecture etc. that I can post to help make the question better.
Thank You
Just search for ContainerBuilder class, and then add this code:
var builder = new ContainerBuilder();
builder.RegisterType<PL_XService>().As<IXService>().InstancePerHttpRequest();
I'm trying to inject specific class into my WCF service but it doesn't work and I can't understand why. I'm VERY NEW to MEF and patterns, just trying to make it work. Watched series of videos to understand what it is about but bootstraping won't work in my case since it is not Silverlight
http://channel9.msdn.com/blogs/mtaulty/mef--silverlight-4-beta-part-1-introduction
Here is my Web application's Global.asax code. This is non MVC, just regular ASP.NET app:
private void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
var catalog = new WebScopedCatalog(new DirectoryCatalog(Server.MapPath("~\\bin")));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
FIRST, I'm not sure I even bootrstrap it properly.. SECOND, I'm using http://www.timjroberts.com/2011/02/web-scoped-mef-parts/ as a guidance for web-scoped parts. I need that because some injected objects supposed to live during request only.
Now, I have following class:
[Export(typeof(ITest))]
[WebPartCreationPolicy(WebCreationPolicy.Session)]
public class Test : ITest
{
public string TestMe()
{
return "Hello!";
}
}
And my service looks like:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MobileService
{
[Import]
public ITest MyTestClass { get; set; }
public MobileService()
{
int i = 10;
}
When breakpoint hits at i=10 - I have NULL inside MyTestClass. Clearly, MEF does not initialize this class for me. Am I missing something?
EDIT:
When I examine catalog - I see my class Exported but I don't see it imported anywhere...
EDIT 2:
Daniel, Thank you. It makes sense. It still feels litle like a magic for me at this point. Yes, WCF creates this service. Than I have MembershipProvider and various Utility classes that ALL need the same import. And I'm not creating neither of those classes so I can't have Mef creating them. (Service created by WCF, MembershipProvider created by who-knows-what, Utility classes have static methods..) I wanted to use Mef instead of storing my stuff in HttpContext.Current. My container object doesn't have SatisfyImports. It has SatisfyImportsOnce. What if I do it in many different constructors? Will Mef share same singleton or it will be creating new instance every time?
At this point I wonder if I should even use Mef in this particular scenario..
MEF won't satisfy imports for objects it doesn't create. What is it that creates MobileService? If it's not MEF, then the import won't be satisfied by default. Even if it is MEF, the import wouldn't be satisfied in the constructor- you can't set properties on an object you create until it is done being created (ie the constructor has finished).
You can call container.SatisfyImportsOnce(mobileService) to satisfy the imports of a part. You should try to avoid doing this everywhere you need a MEF import. If you can, you should export a part and import it from another part so that MEF handles the creation for you. However, it looks like this part may be created by WCF so you can't have MEF create it, and in that case it would be OK to use SatisfyImportsOnce.
Response to EDIT2: If you use the same container each time, MEF will by default only create one instance of the part with the export. You can set the CreationPolicy to NonShared (in either the export or import attribute) to change this.
As for whether it makes sense to use MEF the way you are trying to, I don't know enough about writing web services to give you any advice on that.
The web-scoped part creation policy that I wrote won't help with WCF services.
I've posted a new blog post that documents an approach to composeable WCF services:
http://www.timjroberts.com/2011/08/wcf-services-with-mef/
Basically, you need to implement a custom Instance Provider that is MEF-aware and can compose the WCF service object when it is created.
I wrote about how to compose your WCF in a generic way that its configuration based here:
Unit Testing, WCF and MEF
I actually built my solution on the code samples Tim Robert's provided in his post. only that I took it a bit further and instead of using code in the global asax i moved the configuration into the web.config so its easier to maintain.