I have a ASP.NET web application (not MVC) which is actually a CMS application. I'm trying to set up StructureMap IoC framework and it's working well, but I've now hit a blocker in my understanding.
In my understanding, StructureMap enforces a pattern where all dependencies are registered in the core application assembly, so underlying assemblies do not themselves have a dependency on StructureMap.
So, say my application is My.App and it references another assembly My.Logic. My dependencies are all registered in a Container in My.App. This means that a class in My.Logic can take injected dependencies using a constructor like this:
public class Foo
{
private readonly IBar bar;
public Foo(IBar bar)
{
this.bar = bar;
}
}
But now I have a case where my class in My.Logic is a type which must be registered in the CMS, and this requires that it has an empty constructor.
So the problem is, if I can't inject using constructor parameters, and My.Logic doesn't have a dependency on My.App so I don't have access to the IoC container, is it possible to use StructureMap to handle this scenario?
If not, what alternative do I have other than create the class within the same assembly as the IoC container?
Use setter injection. See here
For<IBar>().Use<MyBar>();
Policies.FillAllPropertiesOfType<IBar>();
Related
i wanna know if it's possible to inject dependency for a class constructor as it is injected for controllers, i have the following cenario as an example:
An AccountController which depends on an AccountRepository like bellow:
public AccountController(IAccountRepository repository)
The dependency is injected perfectly using Unity DI, which have the following configuration:
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager(), accountInjectionConstructor);
container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<IdentityDbContext<ApplicationUser>, ApplicationDbContext>(new HierarchicalLifetimeManager());
The problem is that i have a class AuthorizationServiceProvider which also needs the AccountRepository... In this case, how would i instantiate or use this AuthorizationServiceProvider class without having to instantiate and provide it all the dependencies?
Provider = new SimpleAuthorizationServerProvider>(),
This provider is set inside the Startup class and called before the Unity DI config initializes...
Here the visual studio complains that there's no argument given that corresponds to the class constructor, but if i provide a new AccountRepository i'd have to provide all it's dependencies as well, (ApplicationDbContext context, UserManager userManager) which are already provided for the Unity DI when creating the controllers....
Could somebody help me please?
Thanks in advance...
how would i instantiate or use this AuthorizationServiceProvider class without having to instantiate and provide it all the dependencies?
You can't. This is actually the core of what we're trying to achieve with Dependency Injection. Your application code should let go of the control over its dependencies. This means that your application code should not create an AuthorizationServiceProvider. Rather, it should let a third-party provide this dependency. Typically, this means you require the dependency be supplied using Constructor Injection.
Letting application code create these dependencies itself causes problems, typically referred to as the Control Freak anti-pattern or Dependency Inversion Principle violation. It causes strong coupling, which can hinder maintainability.
When working with Dependency Injection, this third-party is called the Composition Root. The Composition Root is:
a (preferably) unique location in an application where modules are composed together.
With DI, only the Composition Root will create graphs of objects. You are using Unity, which is a DI Container. The DI Container acts as the Composer, which is part of your Composition Root.
Instead of using a DI Container, you can build the object graphs by hand, which means you will have to create a complete tree of dependencies at once. This practice is called Pure DI. Still, the Composition Root is the location where those object graphs are created; with or without a DI Container.
Your view of DI might be troubled by the use of the standard Identity template that Visual Studio provides. From a design and DI perspective, however, this template is horrifying.
Either way, all these stated concepts, patterns and anti-patterns are described quite thoroughly in the book Dependency Injection in .NET by Mark Seemann.
Each tutorial or example that I've found for using DI in ASP.NET 5 only shows how it works with Controllers and Razor Views. I need to use DI for other classes but don't know the proper way to resolve types and provide an instance. Right now I have an instance of a HackyDependencyResolver that everything must reference in order to get the proper instances. I want to either access ASP.NET's service resolver or follow some other best-practice for resolving dependencies.
For example if I have
public class SomeClass
{
public SomeClass(IUseMe useMe)
{
}
}
which is not an ASP.NET MVC Controller. I need a pattern for resolving a correct instance for IUseMe when SomeClass is created. Certainly I can make my own global factory, but is that the best way?
DI has nothing to do with asp.net, controllers or views. In the end all are classes. Considering that an action is an entrypoint in your app, any service you need there should be injected, The service itself has some dependencies and those will be injected automatically by the DI Container when it instantiates the controller.
All you have to do is to define your services (not every object needs injected deps) then register those services into the Di Container.
How do I resolve IUseMe so that I'm not dependent on a particular implementation?
You don't. The Di Container does that based on configuration, when the controller is instantiated. Everything has a flow, you don't just pick classes out of thin air and say "I want this created by the Di container". OK you could, but it would be the wrong approach.
The whole point of using a DI Container is not to care about instantiating services. The framework takes care of integrating with the container, your only job is to define the classes properly and to configure the container .
When using Unity 2.0 for dependency injection within a web application, it appears that user controls, pages, etc will all need make explicit calls to retrieve the container and "fetch" the dependencies … so using the annotations like [dependency] won't offer any value. This is likely since the location of the container (application context, http context cache, etc.) is unknown in the web configuration.
Since Unity itself provides method interception, isn't there a way to "tell" unity how to fetch the container correctly when you build your own web application? Rather than having to create base classes for page, etc.?
The problem is that the WebForms Pages and Controls are not set up to allow for construction by dependency injection, so Unity never gets invoked at all unless the class invokes Unity itself. I've found the best pattern in these cases is to invoke the DI framework in the constructor via a Service Locator and then use annotations to mark dependency properties. Something like this:
public MyPage()
{
// Injector is a wrapper class so you can change the underlying DI framework
// later if necessary.
Injector.Inject(this);
}
[Dependency]
public SomeService MyService {get;set;}
Whenever I try to actually unit test a presenter and a mocked view, I end up running into too many database dependencies
public EditAccount(IAccountEditPage _view, ISession _session, IResponse _response)
{
}
public void view_SaveUser()
{
//Class that takes the view's data and persists it to DB
}
Obviously I can't write unit tests for this presenter because I have a concretion of using my model class that has a strong database dependency.
How am I supposed to removed the dependency on the database without constructor injecting every class that touches the database in my presenter? I don't want to do this every time in every view I have.
I'm using moq, if it helps.
Edit : Also I should mention that the code in "view_SaveUser" is very lean and isn't direct database access or anything like that. It's usually only a few lines. I'm not overstepping the scope of the presenter, AFAIK.
If you don't want to inject the instances on the constructor another option you have is using a setter injection using a IoC framework as Spring.Net or Castle Windsor to inject the dependencies.
Doing this, you would only need to specify on the framework configuration which classes are used for real code and for test project, dependencies would be automatically injected and you would avoid having to use the contructor.
I have a property on my Global.asax.cs class that I need to access from a business class, i.e. using HttpContext.Current.
How do I do this?
Global.asax.cs (in a web project)
public partial class Global : System.Web.HttpApplication
{
public static ProxyGenerator Generator = new ProxyGenerator();
Business class (in a separate business project)
var generator = ((Sei.Osp.Web.Global)HttpContext.Current.ApplicationInstance)
This obviously doesn't work and I don't want to reference the whole web project in the business project as it will create a circular reference (the business project is already referenced in the web project)
UPDATE:
To clarify - the property I'm creating holds an instance of the Castle Dynamic Proxy Generator class. I've read that you shouldn't just create this all over the place.
So I thought I'd create it in my Global.asax.cs and then just use that instance wherever I need to create a proxy class (I'm using it to do AOP)
Is there a better way of doing this?
A better technique would be to create a class (possibly static) with the public static property you want, then reference it from both Global.asax.cs and your business class.
The class could be in your business project, or in a separate project referenced by both your business project and the web project.
Your business classes need to be independent of your web site. You need to reevaluate your reasons for doing it this way. Either the business class doesn't really need access to the property, or the property doesn't need to be in global.asax.