【问题标题】:C# Not getting all properties from GetPropertiesC# 没有从 GetProperties 获取所有属性
【发布时间】:2021-07-07 20:09:39
【问题描述】:

我一直在改变和重新改变不明白为什么我没有得到我想要的价值观,也许有人可以解释一下。

我有这个对象

var result = new GetRatePlanListResponse
        {
            RatePlanId = prodRpsResult.Id,
            RatePlanName = prodRpsResult.Name,
            EffectiveStartDate = prodRpsResult.EffectiveStartDate,
            EffectiveEndDate = prodRpsResult.EffectiveEndDate,
            BillingPeriod = prodRpsResult.PRDP_BillingFrequency__c.HasValue ? prodRpsResult.PRDP_BillingFrequency__c.Value.ToString() : null,
            ShippingSchedule = prodRpsResult.PRDP_DeliveryFrequency__c.HasValue ? prodRpsResult.PRDP_DeliveryFrequency__c.Value.ToString() : null,
            UsageLevel = prodRpsResult?.PRDP_UsageLevel__c,
            IncludedUnits = prodRpsResult?.PRDP_NumberofPackages__c,
            BasePrice = new RatePlanBasePrice
            {
                Currency = pricing != null ? pricing.Currency : string.Empty,
                Price = pricing != null && pricing.Price != null ? pricing.Price.Value : 0
            }
        };

然后我用那个对象调用这个函数:

    public void PriceConverter<T>(ref T obj)
    {
        Type t = obj.GetType();

        foreach (var prop in t.GetProperties())
        {
            if (Enum.GetNames(typeof(RootPrices)).Any(x => x.ToLower() == prop.Name.ToLower()))
            {
                prop.SetValue(obj, ((int)(double.Parse((string)prop.GetValue(obj)) * 100)).ToString(), null);
            }
            
        }

    }

我的问题是由于某种原因我无法访问货币和价格值。我该怎么做?

编辑:

好的,谢谢大家的信息,我决定改变我的方法,因为如果它们内部有其他对象,我无法更改通用对象属性,因为它们代表不同的引用。尽管我正在更改它,但如果有人知道一种递归或迭代更改引用对象及其引用的所有对象并可以提供解决方案的方法,我将不胜感激具有相似字段的预先存在的代码库的多个对象数据。

【问题讨论】:

  • CurrencyPrice 不是传入对象的属性。您可以从 BasePrice 变量引用的对象中获取这些。
  • 你是说它们是 BasePrice 的属性?如果是这样,我怎样才能获得所有的属性和子属性,我应该如何改变我的周期? @艾米
  • IMO,我认为不应该使用反射。我看不出它给你带来了什么,在这里。
  • 我想做一个接收对象的方法,可以遍历所有属性(子属性)并将它们与列表匹配,因此如果需要进行转换,它将自动更改它的值。所以我可以称它为传递对象作为参考,而不必遍历所有对象并手动转换数据。如果您有更好的建议不胜感激

标签: c# foreach getproperties


【解决方案1】:

您可以在 t 中的每个 property 的值上递归调用 PriceConverter&lt;T&gt;。如果您不想对特定类型的属性调用 PriceConverter&lt;T&gt;,则需要实现某种过滤。

对于您给出的简单示例,您可能只需要获取可读、可变的属性即可。此外,看起来ref 关键字不是必需的,因为您可能会改变obj 的属性,但实际上并未更改引用。

void PriceConverter<T>(T obj)
{
    Type t = obj.GetType();
    foreach (var prop in t.GetProperties().Where(p => p.CanRead && p.CanWrite))
    {
        object value = prop.GetValue(obj);
        if (value != null)
        {
            PriceConverter(value);
        }

        if (Enum.GetNames(typeof(RootPrice)).Any(x => x.ToLower() == prop.Name.ToLower()))
        {
            prop.SetValue(obj, ((int)(double.Parse((string)prop.GetValue(obj)) * 100)).ToString(), null);
        }
    }
    
}

【讨论】:

    【解决方案2】:

    CurrencyPrice 都属于RatePlanBasePrice 类型而不是GetRatePlanListResponse。 因此,您必须首先获得BasePrice 属性。如果RatePlanBasePrice 是一个class(不是struct):

      using System.Linq;
      using System.Reflection;
    
      ...  
    
      var prop = obj
        .GetType()
        .GetProperties()
        .FirstOrDefault(p => 
          string.Equals("BasePrice", p.PropertyType) &&
          p.CanRead &&
          typeof(RatePlanBasePrice).IsAssignableFrom(p.PropertyType));
    
      if (prop != null) {
        obj val = prop.GetValue(obj);
    
        if (val != null) {
          RatePlanBasePrice value = (RatePlanBasePrice) val;
    
          // Put relevant code here 
          val.Currency = ...
          val.Price = ...
        }
      }
    

    如果如果RatePlanBasePrice 是一个结构

      var prop = obj
        .GetType()
        .GetProperties()
        .FirstOrDefault(p => 
          string.Equals("BasePrice", p.PropertyType) &&
          p.CanRead && 
          p.CanWrite &&
          typeof(RatePlanBasePrice).IsAssignableFrom(p.PropertyType));
    
      if (prop != null) {
        // uncomment, if you need an old value  
        //var oldValue = (RatePlanBasePrice) (prop.GetValue(obj));
    
        prop.SetValue(obj, new RatePlanBasePrice() {
          // Put relevant code here
          Currency = ...
          Price = ... 
        });
      }
    

    编辑:是的,您可以循环遍历属性,但为什么呢?如果您使用 Linq,则很自然地放置一个查询。 如果您正在寻找某种通用案例,让我们提取一个方法:

    private static bool TryReadProperty<T>(object source, string name, out T value) {
      value = default(T);
    
      if (null == source)
        return false;
    
      var prop = source
        .GetType()
        .GetProperties()
        .FirstOrDefault(p => string.Equals(p.Name, name) &&
                             p.CanRead &&
                             typeof(T).IsAssignableFrom(p.PropertyType));
    
      if (null == prop)
        return false;
    
      value = (T) (prop.GetValue(prop.GetGetMethod().IsStatic ? null : source));
    
      return true;
    }
    

    那么你就可以使用它了

    if (TryGetProperty<RatePlanBasePrice>(obj, "BasePrice", out var value)) {
      // Put relevant code here 
      val.Currency = ...
      val.Price = ...
    }
    

    【讨论】:

    • 是否有办法维持循环,并了解 BasePrice 是一种复杂类型并调用传递该对象的函数?我需要使用 typeof(RatePlanBasePrice) 还是有通用的方法来做到这一点?还是做不到?
    • 你是对的,使用 linq 你可以查询我会尝试使用你的代码,看看我是否能实现我想要的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2022-01-13
    • 2010-11-23
    • 2010-12-30
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多