分配对象时如何防止模型 属性 延迟加载?
How to prevent lazyloading of model property when assigning object?
我正在尝试在客户端的模型上实现一些延迟加载逻辑。
我试图将逻辑放在这些 属性 的 getter 中,但我现在意识到,当创建对象并将其分配给变量时,它会触发所有 getter 属性 从而触发延迟加载逻辑。
型号class:
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 时,其子节点为空。但是将 API 返回的 ProductStructure 分配给变量 'LightProduct' 的简单事实将触发子节点的 getter。 API 使用异步方法,所以我不能使用 ref.
是否有延迟加载对象属性的通用方法?
只要您使用
反序列化您的数据
return JsonConvert.DeserializeObject<ProductStructure>(content, settings);
然后数百个子节点被创建并加载到内存中。您不能为您的场景延迟加载 ProductStructure 中的任何内容。
你应该做的是创建一个 "LightProductStructure" class
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 对象上调用一个方法来反序列化该字符串,并将结果分配给您的子节点 属性。我认为这是您在那种情况下所谈论的延迟加载方法中最接近的方法。
没有。这是一个反模式。
您在 ProductStructure class 中隐藏了 IO / Api 调用。消费者不会知道这些电话的费用。
除非您有令人信服的理由使用外观模式(这是您在此处实施的),否则我会将其分解为两个单独的调用。
-> Product
-> ProductDetails
这将使您的代码更清晰,并且维护您的代码的开发人员更容易理解。
我正在尝试在客户端的模型上实现一些延迟加载逻辑。
我试图将逻辑放在这些 属性 的 getter 中,但我现在意识到,当创建对象并将其分配给变量时,它会触发所有 getter 属性 从而触发延迟加载逻辑。
型号class:
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 时,其子节点为空。但是将 API 返回的 ProductStructure 分配给变量 'LightProduct' 的简单事实将触发子节点的 getter。 API 使用异步方法,所以我不能使用 ref.
是否有延迟加载对象属性的通用方法?
只要您使用
反序列化您的数据return JsonConvert.DeserializeObject<ProductStructure>(content, settings);
然后数百个子节点被创建并加载到内存中。您不能为您的场景延迟加载 ProductStructure 中的任何内容。 你应该做的是创建一个 "LightProductStructure" class
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 对象上调用一个方法来反序列化该字符串,并将结果分配给您的子节点 属性。我认为这是您在那种情况下所谈论的延迟加载方法中最接近的方法。
没有。这是一个反模式。
您在 ProductStructure class 中隐藏了 IO / Api 调用。消费者不会知道这些电话的费用。
除非您有令人信服的理由使用外观模式(这是您在此处实施的),否则我会将其分解为两个单独的调用。
-> Product
-> ProductDetails
这将使您的代码更清晰,并且维护您的代码的开发人员更容易理解。