【问题标题】:C# IoC many instances of the same ViewModel with different IdC# IoC 具有不同 Id 的同一 ViewModel 的许多实例
【发布时间】:2014-08-27 11:52:07
【问题描述】:

我正在使用来自 ServiceStackv3 的 FunQ。我需要从 Container 解析 ViewModel 以获得不同的对象 ID。

基本上构造函数参数应该区分实例(我知道它不是那样工作的,它是例子):

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

及后续:

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

我尝试ReusedWithin 没有成功。

我需要两个实例同时用于表示层,用户需要比较屏幕上的两个对象。

是命名实例唯一选项吗? 我是独立的应用程序,具有自托管的 ServiceStack 主机。

这是我的控制台应用程序:

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);
    }
}

编辑

申请结果:

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

【问题讨论】:

  • 当你说你已经尝试过 ReusedWithin 没有成功你是什么意思。这提供了单例范围、每个请求范围和每次范围的新实例。如果您想重复使用给定的实例,则可以将它们存储在 Dictionary&lt;int,ViewModel&gt; 之类的东西中,然后调用 viewModelDictionary[1] 之类的东西来获取特定实例。
  • @BenRobinson 没错,但由于我的 ViewModel 很大,我正在寻找替代方案。
  • 我大致同意下面 Russ Cam 的回答,Di/IoC 是为服务类型类设计的,而不是 DTO 类型模型。但是为了解决您的具体问题,将实例存储在字典中不会产生很大的开销,字典中唯一的东西就是键和对实例的引用。
  • 进一步更新,在您提供的上下文中,您是否没有某种父视图模型,其中包含您要比较的 2 个子视图模型,例如父 = 订单,子 = 订单项。如果不是,则可能值得创建一个父视图模型来表示包含 2 个子视图的视图,每个视图应该只有 1 个视图模型。
  • @BenRobinson 这是用户需要在屏幕上并排比较两个对象的常见场景。我同时需要两个 OrderViewModel 实例。

标签: c# inversion-of-control funq


【解决方案1】:

仅根据您在问题中提出的内容,我认为您可能错误地使用了控制反转容器:

  1. 您似乎在显式调用容器来解析 ViewModel,我猜是在控制器操作内部。鉴于在应用程序启动时设置了composition root,应用程序对容器的使用应该在很大程度上是透明的。

  2. 使用容器解析 ViewModel 似乎有点奇怪,因为 ViewModel 或多或少是简单的数据传输对象,即 POCO,用于在控制器和视图之间传输模型数据。因为它们是简单的 POCO,所以它们可以很容易地构建,并且没有容器需要满足的依赖关系,因此不需要由容器控制/解决。如果 ViewModel 依赖于操作的结果才能在 View 中显示它,那么 Controller 应该协调这一点并将结果分配给 ViewModel。

如果你能提供更多关于你想要达到的目标的信息,我可能会提供进一步的帮助。

【讨论】:

  • 我正在使用 MVVM,是的,我同意我像 Repository Pattern 一样使用它,是的,我已阅读 devtrends.co.uk/blog/…,但我将在下一个应用程序中更正该设计。我的 ViewModel 包含大型对象并具有 MVVM 内容(命令、事件)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多