My rich domain model has some circular reference, and this is intentional.
I am also writing my own ORM for more control, and to detect changes made to properties I am using Unity to intercept any call to setters and trigger the property change notification (similar with how EF works).
The problem is that I'm getting Stack Overflow, because the policy interception is going over the same object, over and over again. Is there a way to make it do reference counting?
I have already made sure that the constructor aren't circularly dependent, but I still need Policy Injection to stop recursing over the same objects repeatedly.
Instead of injecting the objects, you can inject the functions to built them, when you have a circular reference:
Container.RegisterType<IMyService, ImplService>(... );
public class MyClass {
private Func<IMyService> _serviceProvider;
public MyClass(Func<IMyService> serviceProvider) { _serviceProvider = serviceProvider }
public void DoStuff() {
_serviceProvider().DoSomething();
}
}
Unity will inject a function that returns IMyService
Related
Requiring to sometimes use dependency injection in ActioFilter or other attributes running before or after an action API or result is inevitable. However, it is carried out through passing the type to be injected to the attribute using the typeof keyword. In order to simplify the case, when having various implementations for an interface, I have found it much simpler to manually instantiate the type than using the built-in dependency injection framework. For example:
public TestAttribute: Attribute, IActionFilter {
private Type injectionType;
public TestAttribute(Type injectionType){
...
}
...
public void OnActionExecuting(ActionExecutingContext context) {
InjectedTypeInterface injectedTypInterface = (InjectedTypeInterface) Activator.CreateInstance(injectedType, arg1, arg2, ...);
...
}
}
I want to know, from the point of view of other people here, that would this approach cause problems that using the built-in dependency injection framework would not? (Injected implementation will be always Transient in this case and not Scoped or Singleton)
I don't recommend doing the route of Activator.CreateInstance, here are some reasons why to avoid it and stick with the official way:
You'd need to pass in all instances of the parameters (i.e. of the type you want to instantiate has other dependencies) to it
The instance created this way isn't tracked by the scoped container. This also means, it won't automatically get disposed (Updated note this of course will only happen if the service implements IDisposable interface) at the end of the request and instead be disposed at some indeterminable time in future, when the GC kicks in and will keep resources open for longer then intended (i.e. holding connection or file handle open for longer then intended) unless you dispose it explicitly
Like you already recognized, you can't do so with scoped and singleton instances
For your concrete examples, there are easier ways to get a specific instance from DI - aside from the official supported ways (Filters - Dependency Injection) - you can also resolve from HttpContext, assuming you have access to it in the type of filter you are using.
For ActionFilter/IActionFilter
public void OnActionExecuting(ActionExecutingContext context) {
InjectedTypeInterface injectedTypInterface = context.HttpContext
.RequestServices.GetService<InjectedTypeInterface>();
...
}
I'm struggling with a particular dependency injection problem and I just can't seem to figure it out. FYI: I'm new to guice, but I have experience with other DI frameworks - that's why I believe this shouldn't be to complicated to achieve.
What am I doing:
I'm working on Lagom multi module project and using Guice as DI.
What I would like to achieve:
Inject multiple named instances of some interface implementation (lets' call it publisher, since it will publishing messages to kafka topic) to my service.
This 'publisher' has injected some Lagom and Akka related services (ServiceLocator, ActorSystem, Materializer, etc..).
Now I would like to have two instances of such publisher and each will publish messages to different topic (So one publisher instance per topic).
How would I achieve that?
I have no problem with one instance or multiple instances for the same topic, but if I want to inject different topic name for each instance I have a problem.
So my publisher implementation constructor looks like that:
#Inject
public PublisherImpl(
#Named("topicName") String topic,
ServiceLocator serviceLocator,
ActorSystem actorSystem,
Materializer materializer,
ApplicationLifecycle applicationLifecycle) {
...
}
If I want to create one instance I would do it like this in my ServiceModule:
public class FeedListenerServiceModule extends AbstractModule implements ServiceGuiceSupport {
#Override
protected void configure() {
bindService(MyService.class, MyServiceImpl.class);
bindConstant().annotatedWith(Names.named("topicName")).to("topicOne");
bind(Publisher.class).annotatedWith(Names.named("publisherOne")).to(PublisherImpl.class);
}
}
How would I bind multiple publishers each for it's own topic?
I was playing around with implementing another private module:
public class PublisherModule extends PrivateModule {
private String publisherName;
private String topicName;
public PublisherModule(String publisherName, String topicName) {
this.publisherName = publisherName;
this.topicName = topicName;
}
#Override
protected void configure() {
bindConstant().annotatedWith(Names.named("topicName")).to(topicName);
bind(Publisher.class).annotatedWith(Names.named(publisherName)).to(PublisherImpl.class);
}
}
but this led me nowhere since you can't get injector in you module configuration method:
Injector injector = Guice.createInjector(this); // This will throw IllegalStateException : Re-entry is not allowed
injector.createChildInjector(
new PublisherModule("publisherOne", "topicOne"),
new PublisherModule("publisherTwo", "topicTwo"));
The only solution which is easy and it works is that I change my PublisherImpl to abstract, add him abstract 'getTopic()' method and add two more implementations with topic override.
But this solution is lame. Adding additional inheritance for code reuse is not exactly the best practice. Also I believe that Guice for sure must support such feature.
Any advises are welcome.
KR, Nejc
Don't create a new Injector within a configure method. Instead, install the new modules you create. No child injectors needed—as in the PrivateModule documentation, "Private modules are implemented using parent injectors", so there's a child injector involved anyway.
install(new PublisherModule("publisherOne", "topicOne"));
install(new PublisherModule("publisherTwo", "topicTwo"));
Your technique of using PrivateModule is the one I'd go with in this situation, particularly given the desire to make the bindings available through binding annotations as you have it, and particularly if the full set of topics is known at runtime. You could even put the call to install in a loop.
However, if you need an arbitrary number of implementations, you may want to create an injectable factory or provider to which you can pass a String set at runtime.
public class PublisherProvider {
// You can inject Provider<T> for all T bindings in Guice, automatically, which
// lets you configure in your Module whether or not instances are shared.
#Inject private final Provider<ServiceLocator> serviceLocatorProvider;
// ...
private final Map<String, Publisher> publisherMap = new HashMap<>();
public Publisher publisherFor(String topicName) {
if (publisherMap.containsKey(topicName)) {
return publisherMap.get(topicName);
} else {
PublisherImpl publisherImpl = new PublisherImpl(
topicName, serviceLocatorProvider.get(), actorSystemProvider.get(),
materializerProvider.get(), applicationLifecycleProvider.get());
publisherMap.put(topicName, publisherImpl);
return publisherImpl;
}
}
}
You'd probably want to make the above thread-safe; in addition, you can avoid the explicit constructor call by using assisted injection (FactoryModuleBuilder) or AutoFactory, which will automatically pass through explicit parameters like topicName while injecting DI providers like ServiceLocator (which hopefully has a specific purpose, because you may not need much service-locating within a DI framework anyway!).
(Side note: Don't forget to expose your annotated binding for your PrivateModule. If you don't find yourself injecting your topicName anywhere else, you might also consider using individual #Provides methods with the assisted injection or AutoFactory approach above, but if you expect each Publisher to need a differing object graph you might choose the PrivateModule approach anyway.)
Guice's approach to dependency injection is that the DI framework complements your instantiation logic, it doesn't replace it. Where it can, it will instantiate things for you, but it doesn't try to be too clever about it. It also doesn't confuse configuration (topic names) with dependency injection - it does one thing, DI, and does that one thing well. So you can't use it to configure things, the way you can with Spring for example.
So if you want to instantiate an object with two different parameters, then you instantiate that object with two different parameters - ie, you invoke new twice. This can be done by using provider methods, which are documented here:
https://github.com/google/guice/wiki/ProvidesMethods
In your case, it might look something like adding the following method to your module:
#Provides
#Named("publisherOne")
#Singleton
Publisher providePublisherOne(ServiceLocator serviceLocator,
ActorSystem actorSystem,
Materializer materializer,
ApplicationLifecycle applicationLifecycle) {
return new PublisherImpl("topicOne", serviceLocator,
actorSystem, materializer, applicationLifecycle);
}
Also, you probably want it to be a singleton if you're adding a lifecycle hook, otherwise you could run into memory leaks each time you add a new hook every time it's instantiated.
Say I have two JdbcTemplates, one for "employee_database" and one for "customer_database". Say a class EmployeeDAO requires the former as a constructor dependency, and CustomerDAO requires the latter. If I were writing these classes myself, I'd do
public class EmployeeDAO {
public EmployeeDAO(#Named("employee") JdbcTemplate employeeJdbcTemplate)
and
bind(JdbcTemplate.class).annotatedWith(Names.named("employee")).toInstance(employeeJdbcTemplateInstance);
And likewise for CustomerDAO
But I can't modify EmployeeDAO to add the Named annotation to the constructor parameters.
What's the canonical way to insure the DAO objects get their respective JdbcTemplates in this scenario without having to instantiate them myself?
In a sense, this is similar to the "robot legs problem", as you're trying to create similar-but-slightly-different trees of objects. In the eponymous problem, you're using a reusable Leg object that receives a #Left Foot and a #Right Foot as needed; in this problem, you're similarly varying the binding of an inner object (JdbcTemplate) based on an outer object's (DAO's) context.
A "cheap way" is to use #Provides methods, which is a particularly low-cost solution if your consumer DAOs have few dependencies and are unlikely to change frequently. Naturally, creating a full Provider would also work too, but this syntax works just fine for most cases.
public class YourModule extends AbstractModule {
#Override public void configure() {}
#Provides EmployeeDao createEmployeeDao( // Name doesn't matter.
#Named("employeeJdbcTemplate") JdbcTemplate employeeTemplate,
Dep2 dep2,
Provider<Dep3> dep3Provider) {
return new EmployeeDao(employeeTemplate, dep2, dep3Provider);
}
}
If the dep list is long, deps change frequently, or multiple classes depend on a JdbcTemplate, then private modules may be the way to go.
install(new PrivateModule() {
#Override public void configure() {
bind(JdbcTemplate.class).toInstance(employeeJdbcTemplate);
expose(EmployeeDao.class);
}
});
The example above uses an anonymous inner class, but you could also create a named class (either top-level or nested) that accepts a JdbcTemplate instance and a DAO class literal, and call it like so:
install(new DaoModule(employeeTemplate, EmployeeDao.class));
install(new DaoModule(customerTemplate, CustomerDao.class));
Here is the example code:
public interface IService<TEntity> {
IContext Context { get; set; }
//unimportant methods
bool Validate(TEntity entity);
void Add(TEntity enttity);
}
public class UsersController : Controller {
private IService<User> _service;
public MyController(IService<User> service){
_service = service;
_service.Context = ControllerContext;
}
}
I'm using AutofacControllerFactory to create controllers in my ASP.NET MVC app.
Is it possible to eliminate this line of code in every controller's constructor:
_service.Context = ControllerContext;
In other words: is it possible to automatically set this property with ControllerContext?
It should be possible because every IService implementation has a settable IContext property.
Should I extend the AutofacControllerFactory or is there a standard way of doint this?
What you have there is a Circular Dependency.
UsersController depends on IService<User>
IService<User> depends on ControllerContext
ControllerContext depends on UsersController
No DI Container can reach into your classes' innards and control what happens there. They can set up dependencies for you and inject them into your classes from the outside. However, they can't very well deal with circular dependencies, so a better option is to redesign the API.
From here it looks very much like the Context property of IService<TEntity> is a Leaky Abstraction. A Service shouldn't need to know anything about the UI framework in which it is running.
You can often break a circular dependency by changing one of the consumers to a more event-driven architecture.
Here's an article about this sort of problem.
Here's a related answer to a ASP.NET MVC question that looks a lot like yours: Is there a good/proper way of solving the dependency injection loop problem in the ASP.NET MVC ContactsManager tutorial?
See also the answer: Dependency-Injection to resolve circular dependencies
I Have a custom HandleErrorAttribute that extends FilterAttribute.
How can I have Unity inject dependencies into this attribute at the same time that it injects the controller's dependencies itself?
Ok, figured it out.
Mostly I used Ben's solution above from the blog post he pointed to.
The problem is that Unity behaves a little differently.
You can't inject dependencies on the filters directly, because they are of type IActionFilter and IExceptionFilter respectively. This led me to believe they were readonly, which isn't so. It's just that Unity needs to know the explicit type in order to inject.
So, in the overridden method provided by the article, Unity users need to query the filters for the types in question, and then build them up.
public UnityActionInvoker(IUnityContainer container, IList<Type> typesToInject)
{
_container = container;
_typesToInject = typesToInject;
}
And then in the overridden method, do something like this:
var needsInjection = filters.Where(filter => typesToInject.Contains(filter.GetType()));
A bit messy, but it only needs to be done once, and keeps everything decoupled as Ben suggests.
The other gotcha is that you can't call _container.BuildUp(filter) inside a foreach loop, because the filter is readonly in that context.
You have two options
The first option is to write a custom ActionInvoker, which isn't nearly as hard as it sounds. Check out this blog post. It specifically deals with NInject, but Unity supports property injection so you can modify the example to use Unity.
This is the option that couples your IoC Container and isn't recommended.
public class MyFilter
{
IMyService MyService {get; set;}
MyFilter() : MyFilter(MyUnityContainer.Resolve<IMyService>())
{ }
MyFilter(IMyService service)
{
MyService = service;
}
}
I too came across this problem and now have a working solution. It is similar to the solution described above but with some slight differences and also with the full Unity code added.
First I will be using property injection for the reason described above and, as above, I will be using the BuildUp method on Unity to inject the properties into the already created Filters.
To do this I have all of my Controllers inherit from a new custom base class. On that base class I override the CreateActionInvoker method in order to set my own custom ActionInvoker.
Protected Overrides Function CreateActionInvoker() As System.Web.Mvc.IActionInvoker
Return CustomActionInvoker
End Function
Then in my CustomActionInvoker I override the GetFilters method.
Protected Overrides Function GetFilters(ByVal controllerContext As ControllerContext, ByVal actionDescriptor As ActionDescriptor) As FilterInfo
Dim info = MyBase.GetFilters(controllerContext, actionDescriptor)
For Each MyAuthorizationFilter In info.AuthorizationFilters
MvcApplication.Container.BuildUp(MyAuthorizationFilter.GetType, MyAuthorizationFilter)
Next
For Each MyActionFilter In info.ActionFilters
MvcApplication.Container.BuildUp(MyActionFilter.GetType, MyActionFilter)
Next
For Each MyResultFilter In info.ResultFilters
MvcApplication.Container.BuildUp(MyResultFilter.GetType, MyResultFilter)
Next
For Each MyExceptionFilter In info.ExceptionFilters
MvcApplication.Container.BuildUp(MyExceptionFilter.GetType, MyExceptionFilter)
Next
Return info
End Function
Contrary to what is said above I did not find that doing the buildup inside a For Each loop caused any problems. I also overcame the original problem of only having the object referenced via an interface by using one of the other overloads of the BuildUp method which takes a System.Type as well as the existing object.
With all of the above done I can now inject dependencies straight into my Filters.
Any comments and thoughts very much appreciated.
Cheers Mike