分配对象时如何防止模型属性的延迟加载?

时间:2019-08-02 08:39:37

标签: c# lazy-loading variable-assignment getter

我正在尝试在客户端的模型上实现一些延迟加载逻辑。

我试图将逻辑放入这些属性的getter中,但是现在我意识到,当对象被创建并分配给变量时,它将触发该属性的所有getter,从而触发延迟加载逻辑。

模型类:

    public class ProductStructure
    {
        public override Guid Id { get; set; }

        private List<AbstractStructureNode> subNodes;

        public override List<AbstractStructureNode> SubNodes
        {
            get
            {
                // Lazy loading logic including API calls to set subNodes
                return subNodes;
            }
            set
            {
                subNodes = value;
            }
        }
     }

API:

public async Task<ProductStructure> GetLightProductStructure(Guid Id)
        {
            if (Id == Guid.Empty)
                return null;

            string uri = ServiceUri + $"ProductStructures/Light/{Id}";
            using (var client = new HttpClient())
            {
                HttpResponseMessage response = client.GetAsync(uri).Result;

                if (!response.IsSuccessStatusCode)
                {
                    return null;
                }
                else
                {
                    string content = await response.Content.ReadAsStringAsync();
                    try
                    {
                        JsonSerializerSettings settings = new JsonSerializerSettings()
                        {
                            Formatting = Formatting.None,
                            TypeNameHandling = TypeNameHandling.Auto,
                            SerializationBinder = new CustomJsonSerializer("R3.ProductStructureSDK.DataModel", "R3.ProductStructureSDK")
                        };

                        return JsonConvert.DeserializeObject<ProductStructure>(content, settings);
                    }

                    catch (Exception e)
                    {
                        return null;
                    }
                }
            }
        }

触发延迟加载的分配(单元测试的一部分)

ProductStructure LightProduct = await ProductStructureManager.Instance.GetLightProductStructure(RootId);

从服务器下载ProductStructure时,其子节点为null。但是,将API返回的ProductStructure分配给变量“ LightProduct”的简单事实将触发子节点的获取。该API使用异步方法,因此我无法使用ref。

是否有一种常见的方法来延迟对象的加载属性?

2 个答案:

答案 0 :(得分:2)

不。这是一种反模式。

您将IO / Api调用隐藏在ProductStructure类中。消费者对这些通话的费用一无所知。

除非有令人信服的理由使用外观模式(这是您在此处实现的方式),否则我将其分为两个单独的调用。

-> Product
-> ProductDetails 

这将使您的代码更整洁,并使开发人员更容易维护您的代码。

答案 1 :(得分:1)

使用

反序列化数据后

return JsonConvert.DeserializeObject<ProductStructure>(content, settings);

然后创建了数百个子节点并将其加载到内存中。您无法根据自己的情况在ProductStructure中延迟加载任何内容。 您应该做的是创建一个“ LightProductStructure”类

public class LightProductStructure
{
    public override Guid Id { get; set; }
}

如果需要没有子节点的对象,请使用LightProductStructure对象反序列化服务器的响应。如果需要带有子节点,请使用ProductStructureObject反序列化服务器的响应。

要使代码更整洁,您还应该像这样重构ProductStructure对象

public class ProductStructure : LightProductStructure
{
    private List<AbstractStructureNode> subNodes;

    public override List<AbstractStructureNode> SubNodes
    {
        get
        {
            // Lazy loading logic including API calls to set subNodes
            return subNodes;
        }
        set
        {
            subNodes = value;
        }
    }
 }

修改: 另一种无需继承的方法是-在某些情况下-将子节点作为字符串存储在ProductStructure对象中。这样,您无需加载数百个对象,而在内存中只有一个字符串。 然后,当需要这些对象时,请在ProductStructure对象上调用一个方法,该方法将反序列化该字符串,并将结果分配给Subnodes属性。我认为,在这种情况下,这与您所讨论的惰性加载方法最接近。