C# 如何对动态类型和字符串执行比较运算符
问题描述
我有两个绑定到以下模型的HTTP请求:
public class ShopifyAPI
{
public class ShopifyAPIAuth
{
[Required]
public required string AccessToken { get; set; }
[Required]
public required string Key { get; set; }
[Required]
public required string Secret { get; set; }
}
public class ShopifyOrderResponse
{
[Required]
[JsonPropertyName("orders")]
public required List<ShopifyOrder>? Orders { get; set; }
}
public class ShopifyOrder
{
[Required]
[JsonPropertyName("id")]
public long Id { get; set; }
[Required]
[JsonPropertyName("order_number")]
public required long OrderNumber { get; set; }
[Required]
[JsonPropertyName("financial_status")]
public required string PaymentStatus { get; set; }
[Required]
[JsonPropertyName("shipping_address")]
public required Address ShippingAddress { get; set; }
[Required]
[JsonPropertyName("billing_address")]
public required Address BillingAddress { get; set; }
[Required]
[JsonPropertyName("line_items")]
public required List<Product> Products { get; set; }
}
public class Address
{
[Required]
[JsonPropertyName("first_name")]
public required string FirstName { get; set; }
[Required]
[JsonPropertyName("last_name")]
public required string LastName { get; set; }
[Required]
[JsonPropertyName("address1")]
public required string Address1 { get; set; }
[JsonPropertyName("address2")]
public string? Address2 { get; set; }
[Required]
[JsonPropertyName("city")]
public required string City { get; set; }
[Required]
[JsonPropertyName("province")]
public required string State { get; set; }
[Required]
[JsonPropertyName("zip")]
public required string Zipcode { get; set; }
[Required]
[JsonPropertyName("country")]
public required string Country { get; set; }
[JsonPropertyName("phone")]
public string? Phone { get; set; }
}
public class Product
{
[JsonPropertyName("product_id")]
public long? Id { get; set; }
[JsonPropertyName("title")]
public string? ProductName { get; set; }
[JsonPropertyName("variant_id")]
public long? VariationId { get; set; }
[JsonPropertyName("variant_title")]
public string? VariationName { get; set; }
[JsonPropertyName("quantity")]
public long? Quantity { get; set; }
}
}
和
public class WoocommerceAPI
{
public class WoocommerceAPIAuth
{
[Required]
public required string Key { get; set; }
[Required]
public required string Secret { get; set; }
}
public class WoocommerceOrder
{
[Required]
[JsonPropertyName("id")]
public long Id { get; set; }
[Required]
[JsonPropertyName("status")]
public required string Status { get; set; }
[Required]
[JsonPropertyName("shipping")]
public required Address ShippingAddress { get; set; }
[Required]
[JsonPropertyName("billing")]
public required Address BillingAddress { get; set; }
[Required]
[JsonPropertyName("line_items")]
public required List<Product> Products { get; set; }
[Required]
[JsonPropertyName("meta_data")]
public required List<MetaData> MetaDatas { get; set; }
}
public class Address
{
[Required]
[JsonPropertyName("first_name")]
public required string FirstName { get; set; }
[Required]
[JsonPropertyName("last_name")]
public required string LastName { get; set; }
[Required]
[JsonPropertyName("address_1")]
public required string Address1 { get; set; }
[JsonPropertyName("address_2")]
public string? Address2 { get; set; }
[Required]
[JsonPropertyName("city")]
public required string City { get; set; }
[Required]
[JsonPropertyName("state")]
public required string State { get; set; }
[Required]
[JsonPropertyName("postcode")]
public required string Zipcode { get; set; }
[Required]
[JsonPropertyName("country")]
public required string Country { get; set; }
[JsonPropertyName("phone")]
public string? Phone { get; set; }
}
public class Product
{
[JsonPropertyName("product_id")]
public long? Id { get; set; }
[JsonPropertyName("name")]
public string? ProductName { get; set; }
[JsonPropertyName("variation_id")]
public long? VariationId { get; set; }
[JsonPropertyName("quantity")]
public long? Quantity { get; set; }
}
public class MetaData
{
[Required]
[JsonPropertyName("id")]
public required dynamic Id { get; set; }
[Required]
[JsonPropertyName("key")]
public required dynamic Key { get; set; }
[Required]
[JsonPropertyName("value")]
public required dynamic Value { get; set; }
}
}
我在以下控制器中使用这些模型:
[HttpPost(Name = "PostDataExport")]
[EnableRateLimiting("api")]
public async Task<IActionResult> Post()
{
Task<List<ShopifyOrder>> importShopifyOrders = _shopifyService.GetOrders("https://dirtdudesutv.myshopify.com", _shopifyAPIAuth.AccessToken);
Task<List<WoocommerceOrder>> importWoocommerceOrders = _woocommerceService.GetOrders("https://www.aaaprintco.com", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_woocommerceAPIAuth.Key}:{_woocommerceAPIAuth.Secret}")));
List<Task> tasks = new List<Task> { importShopifyOrders, importWoocommerceOrders };
await Task.WhenAll(tasks);
foreach (var order in importShopifyOrders.Result)
{
bool alreadyImportedOrder = importWoocommerceOrders.Result.Any(o => o.MetaDatas.Any(m =>(m.Key == "_shopify_order_id" && m.Value.ToString() == order.Id.ToString())));
if(alreadyImportedOrder)
{
importShopifyOrders.Result.Remove(order);
}
}
return Ok(importWoocommerceOrders.Result);
}
}
这个控制器的目的是将所有Shopify订单和所有WooCommerce订单拉取出来。然后我需要找出哪些Shopify订单已经在WooCommerce订单中,如果订单存在于foreach循环中所显示的那样,那么就将其从列表中删除。问题在于要检查WooCommerce中的订单是否存在,有一个元数据字段(如模型中所示)有不同的元数据项。其中一个是_shopify_order_id。所以我嵌套了一些任意的LINQ语句来尝试循环查找是否存在。我认为问题在于使用了动态类型,因为元数据的值的类型是不同的。所以当我运行它时,在元数据比较时会出现错误:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Operator '==' cannot be applied to operands of type 'System.Text.Json.JsonElement' and 'string'
at CallSite.Target(Closure, CallSite, Object, String)
我在想,比较字符串与动态类型可能存在问题吗?
解决方案
在两个方面都使用 ToString
进行比较可能会有些棘手。最好使用 string.Equals
,它要求另一个项是字符串:
"_shopify_order_id".Equals(m.Key) && (m.Value.ToString() == order.Id.ToString())
对于订单ID比较,对于使用ToString
也要谨慎 – 如果你有一个ID值为”123″的订单和一个值为123
的键,即使它们的类型不同,比较结果也会为真。
所以你可能也会想要:
"_shopify_order_id".Equals(m.Key) && order.Id.Equals(m.Value)