-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Extensions methods to ActorSystem and ActorContext to make DI more accessible #966
Conversation
I completely agree we shouldn't require calling IDependencyResolver, but I think this is more a workaround then a solution. We should allow Props.Create to use a DI in the background, so system/context.ActorOf and Props.Create can be used without api duplication. This would require some changes to the di implementation, but would make things much cleaner. This |
Don't merge this PR. I'd like to review it and the other conversations going on around DI, but I'm not available to do it until Thursday / Friday. It's come up enough times where I want to understand what the actual issue is. |
@nvivo I agree with it getting cumbersome and I wish for a more and better integrated way to do this and making it so I was just working under the assumption that the way it is currently handled with creating child actors through DI (the example given in the documentation) would be the way to go for now. And adding to that is a fairly easy matter. This way it can be made fairly usable and then later deprecated and also rather easily refactored to the future proper way. The biggest problem currently is if you don't use Akka.net as a first class citizen (building your App on top of it) and just pass around a reference to the The current DI examples are all just one shot console apps that create the But how would you integrate it into a ASP.NET deployment scenario mentioned in the documentation? There you would probably create your Container as a static field in Global.asax, then add the That's btw the exact scenario i currently have to use Akka.net in and that's why i'm struggling so much with it. |
@thomaslazar, you're assumption is correct. The way it works now is based on the existing API from JVM. So I'm using this as a hook to discuss a better API for DI, independently of the merge of this PR, as I'm not the only one that finds the current API odd and hard to use. It seems to me DI in Akka was an afterthought. Any new framework written today takes that as a core concept. We should take into consideration that Akka is 5 years old, and at this point there are lots of legacy components that could be done better today. The Typesafe team is constantly reinventing Akka with better ideas and throwing away old assumptions, and I don't see why we can't do that too instead of just copying everything they do. Even being a port, we should be allowed to improve things every now and then. IMO, the whole problem is this desire to expose DI explicitly, while it should be implicit. If I have this code today: public class A : ReceiveActor {
public A() { ... }
} and change to this: public class A: ReceiveActor {
public A(IDependency dep) {...}
} It shouldn't cause changes to the application code. The app should still work with If we look at the Props today, it's already a kind of manual DI system that builds instances based on dependencies registered in its constructor. Props already uses a
public virtual ActorBase NewActor(IIndirectActorProducer producer) { ... } This would be called by the ActorSystem and actors when a DI was registered, passing the DI producer automatically. To solve the problem of creating Props using DI (the purpose of this PR), the
Considering that Also, note this API is independent of DI. It works exactly as
Props.DefaultProducer = someDIproducer; This would be much simpler, but would set it statically for the whole system. I'm not sure if this would cause any problems though, as I doubt anyone using a DI container would be using 2 in the same app. I'm up for any other solution, as long as we don't have to expose to the application that a DI system is being used like today. cc @jcwrequests |
@nvivo I am all in for your idea to make DI usage more transparent. My proposal is really just a quick fix/addition based on already implemented code to at least make that stuff a little less of a pain. The other thing is I'm just starting out with Akka.net and the Akka way of life in general. So extensions I can handle. Changing Akka.net on a level you proposing I currently can't ;) |
Had a conversation with @rkuhn about DI this morning. What's in this PR is already pretty close to what he and I discussed. Will share some details tomorrow but I think we're close to a working solution that should make DI easier to use. |
@Aaronontheweb Sounds good to me. |
@Aaronontheweb can you share any details on what you and Roland talked about? |
sorry not getting around to this sooner! The high-level points are this:
var router = system.ActorOf(system.DI().Props<TypedWorker>().WithRouter(FromConfig.Instance), "router1"); Should be supported. So if we can clean this PR up to remove the additional |
It makes sense to make DI return props. But removing this now will break the 1.0 api. |
@Aaronontheweb is this the net result of your conversion with @rkuhn ? Or are there more fundamental changes for the DI system coming up ? |
@Danthar that's the net result of the conversation. There's some other interesting ideas that came up (remotely deploying an actor who gets DI'd on the remote system.)
Meant removing them from THIS PR. For everything that's already in the 1.0 API, we have the follow the normal procedure. Mark as |
I can make the necessary changes to the PR to only keep the But this doesn't solve one problem i'm currently having. You can't add additional arguments to the Without DI you can do something like this: With DI you'd probably want that It would be nice to be able to write something like this: This example looks rather crude though with the dictionary. Castle Windsor has a nice extension method for IDictionary that lets you add items to a dictionary with a fluent syntax. http://docs.castleproject.org/Windsor.Arguments.ashx#_Insert_extension_method_4 This extension could be added to the DI Core project. |
Yes, that would be great - thank you!
Mixing and matching In my opinion, I'd try to tackle that problem in its own Issue + PR and have a proper design discussion about it first. Whatever we come up with for solving that problem needs to work across all of the supported DI containers. Would that work? |
That will do fine. I will get on cleaning up the PR tomorrow and add another Issue regarding the other stuff. |
Just to get this straight:
|
The .NET implementation is divergent from JVM's in a few respects. The JVM has the benefit of the We took some liberties with the API and added the So this isn't a "new" design - it's a minor change to our current one. |
Thanks for the discussion and for listening to the advice! To fill in some background, we have arrived at this solution (with just two actorOf variants—with and without a name) due to painful previous experiences. In Akka 1.x there was a plethora of actorOf convenience methods and that poses quite some challenges when it comes to user education as well as library evolution and maintenance. Therefore we switched to a scheme where all the variability is encapsulated in a dedicated type ( Concerning DI the two CLR and the JVM have rather different ecosystems so we might not see full convergence on the design and feature set of exposing DI in Akka / Akka.NET, but I think that is absolutely okay. The beautiful thing about focusing entirely on |
@rkuhn Thanks for your time and explanation. I agree it's a great idea to focus on Props. Now, I really don't care much about convenience methods of ActorOf. What bothers me is the fact that currently DI is explicit in user code. Things like If I my code has I have been looking at the Java implementation, but couldn't find much about it. Do you have any thoughts on that? |
@nvivo My personal opinion is that all essential aspects should be visible—if an essential aspect is hidden from view then that counts as “magic”, that’s exactly how illusionists operate. The fact that If there is a universal and ubiquitous DI mechanism on the CLR that can always be required to exist then it might make sense to teach |
Thanks @rkuhn. That's the kind of answer I was looking for. |
I agree with @rkuhn here, Personally I prefer that once I use DI for a top level actor that using it for child actors becomes an explicit choice, I already have many cases where I want to control the creation of the child actor I do not want it to magically continue to use DI because I created the parent using DI as this is not always what I want to do. |
@stefansedich Just to make it clear, it's not about one or the other. You can always create props manually if you want, and what I said don't prevent that in any way. My view was simply that Akka.NET should be more like the rest of the platform, and that would make it easier for people to use it. There are things that are personal preferences and beliefs, and have nothing to do with what you can or cannot do. I don't agree with the choices made, but I'm glad to know what is the reasoning behind this architecture, as I didn't see any before. |
What do you mean with "more like the rest of the platform"?
|
@stefansedich In DNX (and this includes the normal .NET 4.6 about to be released), DI is a core concept, not an add-on. From the docs: "Core Concepts: Dependency Injection through the entire stack. DI is a core part of the KRuntime, and all libraries we build on top of it." This makes DI automatically available and transparent to any new official .NET framework, including ASP.NET MVC, Entity Framework, SignalR, OWIN middlewares and even console apps. NancyFX does it out of the box too. But again, this is all about personal preferences and I can understand that. |
Just want to make it clear about the previous comment: the point is that no library requires a different syntax to use DI. This can be achieved in Akka and doesn't prevent any scenarios or creates any technical issues, as it doesn't in any other framework. DI doesn't prevent you from manually creating objects, it only makes the default path to not have to. This is the direction the platform is going. It's only about preferences, not limitations. |
- removed ActorOf method - added non generic Props method DIActorContextAdapter.cs - obsoleted ActorOf method - added non generic Props method Examples - updated Examples to use the new syntax Readme.md - updated Examples with new syntax
Cleaned up the pull request. |
@thomaslazar +300 for DIActorSystemAdapter! |
Great job @thomaslazar. This is great! |
Added Extensions methods to ActorSystem and ActorContext to make DI more accessible
@thomaslazar Thumbs Up Here. |
Issue #965
Added a new class
DIActorSystemAdapter.cs
containing methods to extend theActorSystem
with anActorOf
(return anIActorRef
similar to theDIActorContextApapter
method) andProps
(returns aProps
object that can be further configure) method that use DI to create the Actor dependencies.Added a
Props
method toDIActorContextAdapter.cs
similar to theDIActorSystemAdapter
class one.Added a
DI()
extension method forActorSystem
inExtensions.cs
that uses theDIActorSystemAdapter
class.With these changes it is now possible to create
Props
andActors
on theActorSystem
level without having to use aIDependencyResolver
implementation available or throughsystem.GetExtensions<DIExt>().Props
call.It is also possible to now create
Props
from within an Actor through DI and configure it further.