我開始編寫一個非常特定的實用程序方法,它基本上搜索給定對象 - 「searchObj」以獲取字段上的TAttribute,並且如果它找到提供的TAttribute,則相應地使用提供了「updateValue」參數。基本上我最需要的是在搜索提供的對象時:無法通過反射設置字段值
1.如果提供的要搜索的對象的字段具有TAttribute,並且該字段是提供的「conditionType」參數的列表,則相應地將其自身更新爲更新值。
2.如果所提供的對象搜索領域具有TAttribute那場是由「conditionType」參數設置不匹配型的列表,繼續搜索該列表ONLY的匹配字段條件類型,最後如果它找到特定的字段,通過添加或刪除元素來修改List爲「updateValue」列表的大小,並只修改匹配類型批註的那個字段。
因此,對於數字1,它很容易。我面臨的問題是在代碼示例中註釋掉感嘆號。基本上,我試圖訪問和修改該字段的不匹配列表不會設置它的值。他們保持不變,因爲他們從來沒有被修改過。我究竟做錯了什麼?
/// <summary>
/// Updates all object fields marked with TAtrribute with the provided value.
/// The attribute field generic argument must meet the condition type in order the values to be correctly updated.
/// </summary>
/// <typeparam name="TAttribute">The attribute to search for</typeparam>
/// <param name="obj">The actual object which will be searched for the attribute</param>
/// <param name="updateValue">The provided value must be a List<conditionType></param>
public static void UpdateAttributeMarkedField<TAttribute>(object searchObj, object updateValue, Type conditionType) where TAttribute : Attribute
{
Type valueType = updateValue.GetType();
Type objectType = searchObj.GetType();
// Get all the public and instance fields from the object
List<FieldInfo> objectFields = objectType.GetFields(BindingFlags.Instance | BindingFlags.Public).ToList();
// Search all fields and return the ones marked with the [TAttruibute] attribute as list.
List<FieldInfo> markedFields = GetAttributeMarkedField<TAttribute>(objectFields);
for (int i = 0; i < markedFields.Count; i++)
{
IList valueList = null;
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>))
{
valueList = (IList)updateValue;
}
// Make sure we only accept lists both for the "obj" and the "value" arguments
if (markedFields[i].FieldType.IsGenericType && markedFields[i].FieldType.GetGenericTypeDefinition() == typeof(List<>) && valueList != null)
{
Type genericArgument = markedFields[i].FieldType.GetGenericArguments()[0];
// If the marked field is of type List<conditionType> simply just update the values
if (genericArgument == conditionType)
{
markedFields[i].SetValue(searchObj, updateValue);
}
// If the marked field is some other type of list,
// search for the condition type and if there is one, update it with the provided "value" list.
else
{
FieldInfo[] fields = genericArgument.GetFields();
bool meetsCondition = false;
string fieldName = String.Empty;
// If any marked field meets the condition type get the field name
for (int j = 0; j < fields.Length; j++)
if (fields[j].FieldType == conditionType)
{
meetsCondition = true;
fieldName = fields[j].Name;
}
if (meetsCondition == true)
{
IList markedList = (IList)markedFields[i].GetValue(searchObj);
// If the marked list is smaller than the provided value list resize it accordingly by adding the difference.
if (markedList.Count < valueList.Count)
{
int difference = valueList.Count - markedList.Count;
for (int j = 0; j < difference; j++)
{
int index;
index = markedList.Add(Activator.CreateInstance(genericArgument));
// Update the freshly created field from the condition type to match the freshly created value list
// !!!!!!!! DOES NOT SET THE FIELD VALUE !!!!!!!
markedList[index].GetType().GetField(fieldName).SetValue(searchObj, valueList[index]);
}
}
// If the marked list is bigger than the provided value list, resize it accordingly by removing the difference.
else if (markedList.Count > valueList.Count)
{
}
}
}
}
else
{
Debug.LogWarning(@"Currently only lists are supported for the ""obj"" and ""value"" arguments. Skipping update for: " + markedFields[i].GetType());
}
}
}
public static List<FieldInfo> GetAttributeMarkedField<TAttribute>(List<FieldInfo> searchContext) where TAttribute : Attribute
{
List<FieldInfo> result = new List<FieldInfo>();
for (int i = 0; i < searchContext.Count; i++)
if (Attribute.IsDefined(searchContext[i], typeof(TAttribute)))
{
result.Add(searchContext[i]);
}
return result;
}
對!鷹眼! – 2015-02-08 15:25:36