我正在尝试在客户端的模型上实现一些延迟加载逻辑。
我试图将逻辑放入这些属性的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。
是否有一种常见的方法来延迟对象的加载属性?
答案 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属性。我认为,在这种情况下,这与您所讨论的惰性加载方法最接近。