2

I have a PersonEditViewModel which needs two other objects, the personId and the PersonRepository. PersonRepository is obtained from a service locator:

private final int personId;
public PersonEditViewModel(int id) {
    this.personId = id;
    this.personRepository = ServiceLocator.get(PersonRepository.class);
}

But I would like to use dependency injection (DI, IoC) to obtain PersonRepository, preferably via constructor:

public PersonEditViewModel(PersonRepository pr) {
    this.personRepository = pr;
}

My problem is, how can I pass the personId to the constructor in DI pattern? Do I have to make a setter for id - then DI changes the logic of the PersonEditViewModel (the personId field cannot be final)? Is it insufficiency of DI pattern that I cannot pass data objects to the constructor, or do I have to switch my mind and design my ViewModels other way, probably use other patterns to pass data objects to them?

Edit: Changed my question using personId and PersonRepository to be closer to common situations.

  • If you provide a bit more context you might get some answers. Are you using a particular framework and container? What does PersonService do? – Ian Fairman Jun 18 '15 at 9:40
  • @Ian Fairman I've edited the question. It is a general question about DI pattern. – xmedeko Jun 18 '15 at 11:36
1

In addition to what Ian has said in his answer, the following should give you a different perspective around this thing.

I try to answer following two questions about a dependency before I decide on the mechanism to pass the dependency object around.

  1. Am I going to be using the dependency?
  2. Who is responsible for instantiating the dependency?

The answer to first question in your context (I being PersonEditViewModel) is yes. So somehow PersonEditViewModel needs to get hold of appropriate Person instance. Note that "appropriate" is key here but lets look into that in a bit.

Coming to second question, who is responsible for instantiating Person class? Is it your IoC container? I don't think so. You are probably going to be loading appropriate instance of Person class from a database or by calling a REST/WCF service. In any case, you should have another guy in the equation which is responsible for giving you the right Person instance. If you are loading it from database then that guy can be a repository object. In which case, your next dependency is repository. Ask the same set of questions about repository again. Answer to first one is obviously yes. With regards to second one - can IoC container give an instance of (notice, there is no "appropriate" here) a repository. Yes, it can. So that becomes my dependency.

Coming to "Appropriate" - you are putting together this view model for a particular person instance. This particular person instance needs to be fetched from somewhere using right set of parameters like id, email address, name etc. You need a specialised implementation (repository for instance) to do that job. You cannot expect that IoC container would just hydrate this particular object for you somehow.

  • If I use Repository I have to pass Person.Id to the PersonEditViewModel anyway, so it's not a solution to my problem. – xmedeko Jun 18 '15 at 13:47
  • 1
    True. I would not try to get DI container to do that for me. Sometimes, this id would need to passed down to hierarchy of dependencies and it starts becoming serious problem for DI pattern. In those cases, I have use abstractions that help with passing data objects around. This was specific to my use case but I can share details if you are interested. – Suhas Jun 18 '15 at 14:16
  • So it's a shortcoming of DI pattern. I think I can go with a personId setter and remove final keyword. Thank you. – xmedeko Jun 18 '15 at 15:03
0

DI containers are generally used for plugging a limited number of long-lived objects together. Think of them as building the runtime structure of your program. Person looks like an entity to me - it will be loaded, used and discarded often. Also, you could potentially have an unlimited number of Person objects and it would not make much sense to use a container to configure them.

What you probably need is a PersonFactory and/or PersonRepository for managing the lifecycle of Person objects. These can be configured using a container. You could then wrap the factory/repository with another factory/repository that "injects" the Person into the ViewModel. The other services then use this factory/repository to do their work.

Hope that helps a bit.

  • Yes, Person is a short living object, entity or whatever. If I use Repository I have to pass Person.Id to the PersonEditViewModel anyway, so it's not a solution. – xmedeko Jun 18 '15 at 13:44
  • How do you know what Person to create in the first place? Where does that information come from? – Ian Fairman Jun 18 '15 at 13:53
  • I think it's not important. It's about how to pass unmanaged data to the ViewModel. I have changed my question using id and repository to get away from "who creates Person". – xmedeko Jun 18 '15 at 14:04
  • Then I'm not sure I can help. Without knowing what this code is trying to achieve from the user's perspective you're just left with an abstract problem. "how to pass unmanaged data to the ViewModel" has no meaning on its own. – Ian Fairman Jun 18 '15 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.