簡體   English   中英

找不到屬性集方法,System.ArgumentException異常

[英]Property Set Method not found, Exception System.ArgumentException

我正在嘗試復制屬性以更新我的代碼中的供應商

這是我的供應商更新方法

public bool UpdateSupplier(PurchaseOrderHeader header, string newSupplier)
    {
        try
        {
            var oldSupplier = GetSupplierForPoHeader(header);
            Reflection.CopyPropertyValues(oldSupplier, newSupplier);
            Console.WriteLine($"{oldSupplier} : {newSupplier}");
            _context.SaveChanges();
            return true;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            throw;
        }
    }

這是我更新值的方法。

public static void CopyPropertyValues(object source, object destination)
    {
        try
        {
            var destProperties = destination.GetType().GetProperties();

            foreach (var sourceProperty in source.GetType().GetProperties())
            foreach (var destProperty in destProperties)
            {
                if (destProperty.Name != sourceProperty.Name ||
                    !destProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType) ||
                    destProperty.Name == "Id")
                    continue;

                destProperty.SetValue(destination, sourceProperty.GetValue(source, new object[] { }),
                    new object[] { });
                break;
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(@"Inner Exception: "+e.InnerException?.Message);
            Console.WriteLine(@"Message: "+e.Message);
        }
    }

有任何想法嗎?

我檢查了其他堆棧溢出問題,似乎沒有一個問題可以解決我的問題,我對反射還很陌生,所以我不知道如何自己解決這個問題。

檢查這些:

  • 您嘗試設置的屬性需要有一個setter。 PropertyInfo.CanSet
  • 如果setter是私有的,則必須告訴SetValue方法,無論如何應使用BindingFlags對其進行設置(或使用下面的代碼)。
  • 該屬性是派生的,而setter是私有的,並且您仍要設置它,您需要從DeclaringType獲取該屬性,因為在派生類上找不到私有成員(但該屬性是由於公共getter引起的)或使用他們在下面編碼。

如果您想訪問私人設置員,則可能會發現以下有用:

var setterMethod = propertyInfo.GetSetMethod(true);
setterMethod.Invoke(instance, new [] { value });

請注意,您還將獲得Indexers作為屬性。 他們還有一個論點。 您可能還希望排除它們( !propertyInfo.GetIndexParameters().Any() )。

此錯誤意味着您的媒體資源沒有任何set方法。 您沒有幾種方法可以解決此問題,但我僅指出其中的兩種:

1-在您的屬性中實現set方法:

public <type> PropertyName
{
    get;
    set; /// <-- here 
}

2-使用此屬性的后備字段:每個屬性都有其自己的后備字段,與實現方法不同。 如果將屬性實現為: public <type> Name {get;set;}則后備字段的名稱為<Name >k__BackingField ,可以隨意更改。 要獲取后備字段,請使用以下代碼:

meObject.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where(prop => prop.Name.EndsWith("__BackingField"));

這將返回您的自動財產支持字段。


對您的問題做出最后結論。 不要使用GetProperties()因為屬性始終具有一些后備字段。 請改用GetFields()因為所有屬性所做的只是修改其后備字段或返回(幾乎)恆定值。

在線示例

GetProperties()方法有一個重載,它需要BindingFlags指定進行反射搜索的方式。

source.GetType().GetProperties(BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.Public) // ... & and other flags you need

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM