我為我之前的帖子道歉,我會在這里嘗試更詳細。
我有一些 DTO 類,包含 100 多個屬性,這些屬性又具有多個屬性,其中包含更多與屬性相關的資料。例如:
[JsonPropertyName("saldo")]
[DisplayData("Saldo", Unit.Currency)]
[Section(Section.Taxes)]
public string saldo { get; set; }
其他屬性可能有更多屬性,而其他屬性可能更少。當我從 API 獲取資料時,我將流反序列化為指定的 DTO 類。完成后,我會進行反射部分以提取所有資料。
public async Task<IEnumerable<DTOPropertyInfo>> GetPropertiesInfoAsync(BaseDTO dto)
{
List<DTOPropertyInfo> info = new();
List<DTOPropertyInfo> favorites = new();
QueryType type = dto.ToQueryType();
PropertyInfo[] properties = dto.GetType().GetProperties();
for (int i = 0; i < properties.Length; i )
{
PropertyInfo property = properties[i];
DisplayDataAttribute display =
(DisplayDataAttribute)property.GetCustomAttribute(typeof(DisplayDataAttribute));
if (display is null)
{
continue;
}
object value = property.GetValue(dto);
if (value is BaseDTO[] dtos)
{
for (int j = 0; j < dtos.Length; j )
{
IEnumerable<DTOPropertyInfo> nestedInfo =
await GetPropertiesInfoAsync(dtos[j]);
info.Add(new()
{
DisplayName = $"{display.DisplayName} {j 1}",
Value = nestedInfo,
Section = Section.SubSection
});
}
continue;
}
else if (value is string[] strings)
{
if (strings.Length == 0)
{
continue;
}
List<DTOPropertyInfo> dtoProperties = new();
for (int j = 0; j < strings.Length; j )
{
dtoProperties.Add(new()
{
DisplayName = (j 1).ToString(),
Value = strings[j]
});
}
info.Add(new()
{
DisplayName = display.DisplayName,
Value = dtoProperties,
Section = Section.SubSection
});
continue;
}
else if (property.PropertyType.IsArray)
{
//Only support arrays of type string[] and BaseDTO[]
//If more needed, add them to the if-chain
continue;
}
value = (value as string).FormatDisplayValue();
if (string.IsNullOrEmpty(value.ToString()))
{
continue;
}
SectionAttribute section =
(SectionAttribute)property.GetCustomAttribute(typeof(SectionAttribute));
if (section is null)
{
section = (SectionAttribute)dto.GetType().GetCustomAttribute(typeof(SectionAttribute));
if (section is null)
{
continue;
}
}
if (type is not QueryType.None)
{
string favorite = await storage.GetAsync($"{type}/{display.DisplayName}");
if (!string.IsNullOrEmpty(favorite))
{
favorites.Add(new()
{
DisplayName = favorite,
Value = value,
IsFavorite = true,
Section = section.Section,
Unit = display.Unit
});
continue;
}
}
info.Add(new()
{
DisplayName = display.DisplayName,
Value = value,
Section = section.Section,
Unit = display.Unit
});
}
info.InsertRange(0, favorites);
return info;
}
DTOPropertyInfo 如下所示:
public readonly struct DTOPropertyInfo
{
public readonly string DisplayName { get; init; }
public readonly Section Section { get; init; }
public readonly object Value { get; init; }
public readonly bool IsFavorite { get; init; }
public readonly Unit Unit { get; init; }
public DTOPropertyInfo(string name, Section section, string value, bool favorite, Unit unit)
{
DisplayName = name;
Section = section;
Value = value;
IsFavorite = favorite;
Unit = unit;
}
}
該應用程式是使用 .NET MAUI 構建的,我還沒有真正進行任何“正確”測驗,我已經在幾部 iOS 手機(新舊手機)上安裝了該應用程式。與 Android 手機(舊款和新款)相同,它們的行為都相同。iOS 在進行反射時完全沒有問題,一切都是即時的。但是,Android 手機在做反射部分時確實很慢。盡管較新的 Android 手機的性能確實比舊手機好一點,但性能損失仍然相當明顯。
我想我可以手動寫出每一個屬性,但這會非常非常乏味。
uj5u.com熱心網友回復:
反射繁重的代碼有一些技巧
不要多次做某事
你所做的大部分事情都取決于dto.GetType(); 每個型別的資料不會因實體/使用而改變,但反射大部分時間都需要新物件,所以:不要那樣做!考慮添加快取,例如:
static readonly ConcurrentDictionary<Type, EverythingYouNeedHere> s_TypeData = new();
現在您可以檢查快取 ( TryGetValue) 并且大多數時候:做零作業。只需在它不存在時進行作業,然后添加它。
在你真的不想要反射的高級場景中,你可以使用“生成器”或類似的東西來將這種作業轉移到構建時間,但這要困難得多。靜態快取方法解決了 95% 的反射問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/514893.html
上一篇:如果所選日期不可用,則顯示警告
