0

I'm using FunQ from ServiceStackv3. I need resolve ViewModel from Container for different object Ids.

Basically constructor parameter should distinguish between instances (I know it does not work that way, it's example):

var vm1 = EndpointHost.Container.Resolve<ViewModel, int>(1);
var vm2 = EndpointHost.Container.Resolve<ViewModel, int>(2);

and subsequent:

var vm3 = EndpointHost.Container.Resolve<ViewModel, int>(1);
Assert.Equal(vm1 == vm3)

I have try ReusedWithin with no success.

I need two instances at the same time for presentation layer, user need to compare two objects on screen.

Is named instance only option? I's standalone application, with self hosted ServiceStack host.

Here is my console application:

public class Program
{
    private static void Main(string[] args)
    {
        Console.WriteLine("Start");
        var appHost = new AppHost();

        var vm1 = EndpointHost.Container.Resolve<ViewModel, int>(1);
        Console.WriteLine("Id1=" + vm1.SomeSomeId + " Instances=" + ViewModel.Instances);

        var vm2 = EndpointHost.Container.Resolve<ViewModel, int>(2);

        Console.WriteLine("Id2=" + vm2.SomeSomeId + " Instances=" +     ViewModel.Instances);

        var vm3 = EndpointHost.Container.Resolve<ViewModel, int>(1);

        Console.WriteLine("Id3=" + vm3.SomeSomeId + " Instances=" + ViewModel.Instances);

        Console.WriteLine("Stop");
        Console.ReadKey();
    }
}

public class AppHost : AppHostHttpListenerBase
{
    public AppHost()
        : base("Test Service", typeof(Program).Assembly)
    {
        Init();
        Start("http://*:8082/");
    }

    public override void Configure(Container container)
    {
        container.Register<ViewModel, int>((c, i) => new ViewModel(i));
    }
}

public class ViewModel
{
    public static int Instances = 0;

    public int SomeSomeId { get; set; }

    public ViewModel(int someId)
    {
        SomeSomeId = someId;

        Interlocked.Increment(ref Instances);
    }
}

Edit

Application results:

ReusedWithin(ReuseScope.Default, Container, Request) 
Id1=1 Instances=1 Id2=1 Instances=1 Id3=1 Instances=1

ReusedWithin(ReuseScope.None) 
Id1=1 Instances=1 Id2=2 Instances=2 Id3=1 Instances=3
Tomasito
  • 1,864
  • 1
  • 20
  • 43
  • When you say you have tried ReusedWithin with no success what do you mean. That offers singleton scope, per request scope and new instance every time scope. If you want to re-use a given instance then you can stored them in something like a `Dictionary` then call something like `viewModelDictionary[1]` to get a specific instance. – Ben Robinson Aug 27 '14 at 12:04
  • @BenRobinson that's correct but since my ViewModel is pretty big, I'm looking for alternative. – Tomasito Aug 27 '14 at 12:25
  • I broadly agree with Russ Cam's answer below, Di/IoC is designed for service type classes, not DTO type models. But to address your specific point, storing the instances in a dictionary would not be a significant overhead, the only thing in the dictionary would be the key and a reference to the instance. – Ben Robinson Aug 27 '14 at 12:30
  • Further to your updates, in the context that you provide do you not have some kind of parent view model, that contains the 2 child view models that you want to compare, e.g. parent = order, children = line items. If not it might be worth creating a parent view model to represent the view that contains the 2 children, you should only have 1 view model per view. – Ben Robinson Aug 27 '14 at 12:50
  • @BenRobinson Which is the common scenario when user needs to compare two objects side by side on screen. I need two instances of OrderViewModel at the same time. – Tomasito Aug 27 '14 at 12:59

1 Answers1

1

Based only on what you have put in your question, I believe that you may be using an Inversion of Control container incorrectly:

  1. You seem to be explicitly calling the container to resolve a ViewModel, I'm guessing inside of a controller action. The usage of the container by the application should be largely transparent given the setup of the composition root on application startup.

  2. Using the container to resolve ViewModels appears a little strange in that ViewModels are more or less simple Data Transfer Objects i.e. POCOs, for transferring Model data between Controllers and Views. Because they are simple POCOs, they can be constructed easily and have no dependencies to be satisfied by the container and hence need not be controlled/resolved by the container. If a ViewModel depends upon the outcome of an operation in order to display it in the View, then the Controller should coordinate this and assign the outcome to the ViewModel.

If you can provide more information behind what you are trying to achieve, I may be able to help further.

Russ Cam
  • 124,184
  • 33
  • 204
  • 266
  • I'm using MVVM, Yes I agree that I'm using it like Repository Pattern and Yes, I have read http://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container but I'll correct that design in next application. My ViewModel holds large objects and have MVVM stuff (Commands, Events). – Tomasito Aug 27 '14 at 12:18