How to replicate this code with Autofac syntax?
public static class MenuConfig
{
public static void Initialize()
{
var _menuService = DependecyFactory.GetInstance<IMenuService>();
Parameters.Menu = _menuService.Menu();
}
}
Before calling this a "duplicate question" please note that I'm looking for an Autofac command. I CANNOT inject the interface anywhere and then call "Resolve". What I need to is perform an "InstancePerRequest" inline and uninjected so I don't have to do this:
var _service = new Service(new Dependency(new context()));
LightInject has a method that allows instantiation from an interface OUTSIDE of a constructor like this:
var _service = DependecyFactory.GetInstance<IService>();
What is the equivalent method for Autofac?
When calling containerBuilder.Build() you get back a container which implements IContainer and ILifetimeScope, whenever you get hold of one of these interfaces, you can resolve types from it:
container.Resolve<IService>();
If you want this container to be static, you could add the container as a static property to the Program or Startup class (depending if you're creating a Console or ASP.NET application).
Remember that the root container will be around for the entire duration of your application, so this can result in unwanted memory leaks when used incorrectly. Also see the warning in the documentation.
Still, it's perfectly possible to do the memory management yourself by resolving an Owned<> version from your interface:
using (var service = Program.Container.Resolve<Owned<IService>>())
{
service.Value.UseService();
}
Anyway, since you mention a static class in the comments, the best solution is to change that into a non-static class and register it as a singleton with Autofac. Then you can inject a Func<Owned<IService>> serviceFactory into that singleton and create/dispose an instance of the service wherever you need it.
using (var service = serviceFactory())
{
service.Value.UseService();
}
This is simply not possible with Autofac. All other solutions involving Autofac will require code refactoring which may potentially break software functionality. So unfortunately, the most elegant and least disruptive solution is this:
var _service = new Service(new Dependency(new context()));
Since this is an edge case addressing only one part of the software, this compromise is acceptable. It would be nice, however, if Autofac implemented this functionality in some future release.
Related
I have a class "DependencyResolver" where I return instances of objects by hand. There I used "Activator.CreateInstance".
I wanted to change it so it uses autofac.
My function "Get" works fine:
public T Get<T>()
{
return _container.Resolve<T>();
}
But I also have a function "CreateNew" where I need a new instance:
public T CreateNew<T>()
{
return _container.Resolve<T>();
}
The Problem is that I always get the same instance.
My Registration looks like this:
var builder = new ContainerBuilder();
foreach (var dllFileName in DependencyMapping.GetAllDllFilenames())
{
builder
.RegisterAssemblyTypes(Assembly.LoadFile(Path.Combine(GetPathFromInstalledSys(), dllFileName)))
.AsImplementedInterfaces()
.SingleInstance();
}
_container = builder.Build();
So there is a place where I can control the behaviour: "SingleInstance" or "InstancePerDependency". But I dont know whether the user needs a new instance or not. Is there any way to change the behavior when "CreateNew" is called?
Lifetime scope (single instance, instance per dependency) is controlled at registration time, not resolve time. There's no way to change it. This is the case with all DI containers, not just Autofac. Part of the point of it is that the consumer shouldn't have to know what scope they want - they just ask for a thing and get it.
Consumers also generally shouldn't deal with disposal - things get disposed by the container.
Note what you have here is service location (client asks the container for a thing), not dependency injection (client takes dependencies in constructor and doesn't know about the container). While service location is sometimes required, generally try to avoid it if you can; it's not really much better than just calling new in your code.
I am doing a course of MVVM for Xamarin Forms, and the teacher in one class used FreshIOC.Container.Register to "register different instances or dependencies", and I don't understand how that affects my code, if someone can explain it I would appreciate it.
My code as an example:
public App()
{
InitializeComponent();
FreshIOC.Container.Register<IContactService,ContactService>();
FreshIOC.Container.Register<IUserDialogs>(UserDialogs.Instance);
}
class MainViewModel : FreshBasePageModel
{
private IContactService service;
private IUserDialogs dialog;
public MainViewModel(IContactService Service, IUserDialogs Dialog)
{
service = Service;
dialog = Dialog;
}
public override async void Init(object initData)
{
dialog.ShowLoading();
var tempt = await service.GetData();
Contacts = tempt;
dialog.HideLoading();
}
}
I don't see what FreshIOC.Container.Register does, or how it connects to the MainViewModel class. By the way, there is another method called "Resolve" instead of "Register", If you could also explain that one I would appreciate it.
That is all, if you need anything more from my code I will provide it as soon as I see your request, thank you all so much for your time, have a nice day.
The Register registers your concrete classes at the IoC framework.
So, IoC in short will work like this:
Instead of making new ContactService all the time, you'll ask the IoC framework to give you one.
This has some benifits;
because you often register by interface, you only need to worry about the ContractService constructor at one place, and not all over the place.
it makes your code better testable because the consuming page is not responsible for creating the service. This might sound a bit mystic, but if you write unit test, you'll immediate see the benefits.
what does Register do?
It makes sure you can request this service from the IoC framework.
The first one registers the ContactService as an IContactService; so, if you request an IContactService you'll get the registered type.
The second one registers the instance of a type: if you request it, you'll always get that instance. Works well for settings and thread safe stuff. Works not at all for database related things.
What does Resolve do?
It enables you to retrieve a service from the IoC framework, but note: there might be better ways e.g. by constructor injection.
This code is an example of constructor injection: by registering the IContactService you've enabled the possibility to resolve the service automatically. If you ommit the registration this is not possible:
public MainViewModel(IContactService Service, IUserDialogs Dialog)
{
service = Service;
dialog = Dialog;
}
If you didnt use the IoC framework, you would have ended up with new ContactService in every model you where using, which can be considered as an antipattern for such services, because;
changing the implementation concrete type will result in a lot of code changes.
changing the constructor would lead to a lot of code changes
unittesting the consumer causes an instantation of the service, which can lead to side effects.
Is it bad If I use the ServiceProvider interface to resolve my properties in .NET Core for Dependency Injection
let say I have the following
private readonly IRecipeRepository _recipeRepository;
private readonly IMediaResource _resourceUpload;
private readonly IAWSMedia _awsMedia;
and then do this
public RecipeService(IServiceProvider service)
{
_recipeRepository = service.GetService<IRecipeRepository>();
_resourceUpload = service.GetService<IMediaResource>();
_awsMedia = service.GetService<IAWSMedia>();
}
instead of this
public RecipeService(IRecipeRepository recipeRepo, IMediaResource media, IAWSMedia awsMedia )
{
_recipeRepository = recipeRepo;
_resourceUpload = media;
_awsMedia = awsMedia ;
}
The first bit of code is called the service locator anti-pattern, as in something you should not do. However, the answer to your question depends on context you have not provided.
In the majority of cases, no, you should not just inject IServiceProvider. However, in some scenarios, you have no choice but to: namely with things in singleton scope. If you have a singleton-type class, an IHostedService implementation, etc., you cannot inject anything but other singleton-scoped services. If you need something in a different scope like a DbContext, then you can only get that by injecting IServiceProvider and creating a scope:
using (var scope = _serviceProvider.CreateScope())
{
var foo = scope.ServiceProvider.GetRequiredService<Foo>();
// do something with foo;
}
However, remember that the instance retrieved is tied to the scope. In other words, when the using statement closes, it will be disposed. Therefore, you need to do any work with that instance inside that scope. You cannot do something like set an instance variable on your class, and the attempt to use it later, as you'll then get an ObjectDisposedException.
I have an application that creates a lifetime scope at some point like so:
public class Main
{
public void Main()
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
scope.Resolve<SomeClass>();
}
}
}
Within SomeClass I have logic which then calls a lot of different classes and so on..
Then, about 10 methods down the call stack I need to use the main scope to do this:
public class ActivatorFactory : IActivatorFactory
{
public T Create<T>(Type instance)
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
return (T)scope.Resolve(instance);
}
}
}
The problem with that is that now I've created a new scope which is just used to resolve a runtime type. I want to be able to use the main scope to resolve this type. How can I do so without passing the main scope down to this factory class through 10 different methods/functions?
The only "hacky" solution I thought of is to just have a static property on my ActivatorFactory and set the scope in my Main class like so:
public class Main
{
public void Main()
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
ActivatorFactory.Scope = scope;
scope.Resolve<SomeClass>();
}
}
}
Is there a cleaner solution to use the main scope in another part of my application?
I had this need for a CancellationTokenSource instance per lifetime scope, where children are linked to their parent. If the the root scope's CancellationTokenSource, is canceled, all children lifetime scope's CancellationToken are canceled. To accomplish this, I created:
private sealed class ParentLifetimeScopeAccessor
{
private readonly ILifetimeScope _lifetimeScope;
public ParentLifetimeScopeAccessor(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
_lifetimeScope.ChildLifetimeScopeBeginning += OnChildLifetimeScopeBeginning;
}
public ILifetimeScope ParentLifetimeScope { get; private set; }
private void OnChildLifetimeScopeBeginning(object sender, LifetimeScopeBeginningEventArgs e) =>
e.LifetimeScope.Resolve<ParentLifetimeScopeAccessor>().ParentLifetimeScope = _lifetimeScope;
}
With a registration, you can now access your parent's scope:
builder.RegisterType<ParentLifetimeScopeAccessor>().InstancePerLifetimeScope();
With the parent lifetime scope accessor, linked CancellationTokenSource instances can be created:
private static CancellationTokenSource CancellationTokenSourceFactory(IComponentContext context)
{
var scopeAccessor = context.Resolve<ParentLifetimeScopeAccessor>();
var parentScope = scopeAccessor.ParentLifetimeScope;
return null == parentScope
? new CancellationTokenSource()
: CancellationTokenSource.CreateLinkedTokenSource(parentScope.Resolve<CancellationTokenSource>().Token);
}
CancellationToken resolver:
private static CancellationToken CancellationTokenResolver(IComponentContext context) =>
context.Resolve<CancellationTokenSource>().Token;
Two registrations:
builder.Register(CancellationTokenSourceFactory).AsSelf().InstancePerLifetimeScope();
builder.Register(CancellationTokenResolver).AsSelf().InstancePerDependency();
If you're not using ActivatorFactory for your app (and you shouldn't be if you're using inversion of control) then delete it and think about what you're trying to test.
Are you trying to test that you can generally just resolve things from Autofac? Autofac has a raft of unit tests as well as millions of successful users. No value in testing the framework.
Are you trying to test that you registered all the things you needed to register? There's not a lot of value in that, either, for a couple of reasons: first, you'll hit that at runtime pretty quickly and see it in those tests; second, in a large, decoupled system those tests get really stale really quickly. It's a maintenance hassle.
Are you trying to test that a specific object graph can be composed based on your registrations? I might buy this one. See below.
Let's say it's the last thing - you have a really complex and troublesome object graph you want to ensure you can create because people keep breaking it. I could see that.
Separate your registrations out into an Autofac module. Use the Autofac module to test.
public class MyRegistrations : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Thing>();
// and all your other registrations.
}
}
then in the unit test
var builder = new ContainerBuilder();
builder.RegisterModule<MyRegistrations>();
var container = builder.Build();
var thing = container.Resolve<Thing>();
// Assert on the resolved thing.
You can use that same module to encapsulate your registrations in the app and then you'll actually be testing the complex registration but without a factory you're not using.
Warning: It is a slippery slope between testing some complex registration and testing all registrations. Like I said, you really don't want to test every registration you have. I've fallen down this slope. It's a maintenance nightmare. Add a registration to the module/app, add a test. Uh oh, we refactored, now the registrations are all different. Ugh. That's less testing about behavior than about characterization (not "what do I want it to do" but "what does it do now"). Pain. Suffering.
If you are using ActivatorFactory in your app for, say, service location instead of using some more standard thing like CommonServiceLocator that already does that for you and for which Autofac already directly integrates... then just test ActivatorFactory with a real container but with some arbitrary test registrations rather than the whole set from the real app. The functionality of ActivatorFactory doesn't have any bearing on what's registered inside it.
And, yeah, if you're using ActivatorFactory and need to keep it around, you'll have to hand it an ILifetimeScope at app startup. That's how service locators work. You'll see that all over in the Autofac docs when you look at how to integrate with apps like ASP.NET, WCF, and others.
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.