首页 > 解决方案 > MVVM 结合多数据源

问题描述

我从不同的 Web API 收集数据(因为我想让用户选择他们想要使用的来源)。即使数据具有相同类型的信息,数据模型也是不同的。

例如,一个 API 发送了这个模型:

public partial class Data
{
    [JsonProperty("code")]
    public int Code{ get; set; }

    [JsonProperty("type")]
    public Info Type { get; set; }

    [JsonProperty("person")]
    public Info Person{ get; set; }
}

public partial class Info
{
    [JsonProperty("elementid")]
    public int ElementId { get; set; }

    [JsonProperty("$", NullValueHandling = NullValueHandling.Ignore)]
    public string Name { get; set; }
}

另一个 API 发送了这个:

public partial class Data
{
    [JsonProperty("id")]           // This is corresponding to Code for previous api, it is easy to change
    public int Code { get; set; }

    [JsonProperty("name")]
    public string name { get; set; }    // This one is Type.Name => type problem

    [JsonProperty("person")]           // This data exists in both models but this is not the same type 
                                       // (but i can merge Info class from the first model with the Member class)
    public Member Person{ get; set; }
}

public partial class Member
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("activity")]
    public string Activity { get; set; }

    [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)]
    public string PictureUrl { get; set; }
}

在此示例中,我可以为某些 API 创建虚拟属性以拥有一个独特的模型。

问题是数据模型比那些代码复杂得多,我使用了四个源(所以,四个模型也是)。

目前,我使用一个非常痛苦和肮脏的代码来实现我的目标(这里只是一个例子,很多行需要相同的结构,OnPropertyChanged定义了四次!!!):

if (myGrid.DataContext.GetType() == typeof(Sources.SourceA) && mySourceA != null)
{
    mySourceA.IsFileSaved = true;
}
else if (myGrid.DataContext.GetType() == typeof(Sources.SourceB) && mySourceB != null)
{
    mySourceB.IsFileSaved = true;
}
else if (myGrid.DataContext.GetType() == typeof(Sources.SourceC) && mySourceC != null)
{
    mySourceC.IsFileSaved = true;
}
else if (myGrid.DataContext.GetType() == typeof(Sources.SourceD) && mySourceD != null)
{
    mySourceD.IsFileSaved = true;
}

当然,我想在这里获得的只是:

if (mySources != null)   // I know what model is used for DataContext !
{
    mySources.IsFileSaved = true;
}

我的问题很简单,因为答案可能(应该?)很复杂:):我怎样才能只使用一个具有多个来源的模型?(也许我在尝试合并所有模型时没有以正确的方式进行,但我已经尝试了很多方式)

当然,只使用一个来源是最简单的方法,但我不想这样做。

谢谢你的想法......和你的解决方案(我希望如此:))

标签: c#

解决方案


您可以做到这一点的一种方法是使用策略模式。创建一个ISource接口,如下所示:

namespace StrategySource
{
    public interface ISource
    {
        bool IsFileSaved { get; set; }

        // add any other common properties...
    }
}

请注意,该ISource接口包含IsFileSaved所有源共有的属性。根据需要将任何其他常用成员添加到此接口。

然后让你的类实现这个接口,像这样:

namespace StrategySource
{
    class SourceA : ISource
    {
        private bool isFileSaved;

        // replace with your own custom implementation
        public bool IsFileSaved
        {
            get { return isFileSaved; }
            set { isFileSaved = value; }
        }
    }

    class SourceB : ISource
    {
        private bool isFileSaved;

        // replace with your own custom implementation
        public bool IsFileSaved
        {
            get { return isFileSaved; }
            set { isFileSaved = value; }
        }
    }

    // other sources ...
}

每个SourceN类都实现ISource. 那是一份合同——由于这份合同,你知道他们也IsFileSaved有财产。

您可以拥有任意数量的SourceN类来实现ISource。这为您提供了面向未来的可扩展性。

这使您可以一次性编写代码,如下所示:

using System.Collections.Generic;

namespace StrategySource
{
    class Program
    {
        static void Main(string[] args)
        {
            List<ISource> sources = GetSources();

            foreach (var source in sources)
                if (source != null)
                    source.IsFileSaved = true;
        }

        static List<ISource> GetSources()
        {
            return new List<ISource>
            {
                new SourceA(),
                new SourceB()
                // and so on
            };
        }
    }
}

我使用 将GetSources这些中的每一个都拉到一个集合中,听起来您已经有了执行此操作的代码。

这里的重点是,因为每个SourceN类都实现了相同的接口,所以您可以编写一个以相同方式对所有类进行操作的算法。您可能听说过这称为接口多态性。


推荐阅读