Индексированные свойства отражения C#
-
08-07-2019 - |
Вопрос
Я пишу метод Clone, используя отражение.Как определить, что свойство является индексированным, используя отражение?Например:
public string[] Items
{
get;
set;
}
Мой метод на данный момент:
public static T Clone<T>(T from, List<string> propertiesToIgnore) where T : new()
{
T to = new T();
Type myType = from.GetType();
PropertyInfo[] myProperties = myType.GetProperties();
for (int i = 0; i < myProperties.Length; i++)
{
if (myProperties[i].CanWrite && !propertiesToIgnore.Contains(myProperties[i].Name))
{
myProperties[i].SetValue(to,myProperties[i].GetValue(from,null),null);
}
}
return to;
}
Решение
if (propertyInfo.GetIndexParameters().Length > 0)
{
// Property is an indexer
}
Другие советы
Извините, но
public string[] Items { get; set; }
не является индексированным свойством, это просто тип массива! Однако следующее:
public string this[int index]
{
get { ... }
set { ... }
}
Вам нужен метод GetIndexParameters ()
. Если возвращаемый массив содержит более 0 элементов, это означает, что это индексированное свойство.
Подробнее см. документацию MSDN . подробности.
Если вы вызываете property.GetValue (obj, null)
и свойство индексируется, вы получите исключение несоответствия количества параметров. Лучше проверить, индексируется ли свойство с помощью GetIndexParameters ()
, а затем решить, что делать. Р>
Вот код, который сработал у меня:
foreach (PropertyInfo property in obj.GetType().GetProperties()) { object value = property.GetValue(obj, null); if (value is object[]) { .... } }
P.S. .GetIndexParameters().Length > 0)
работает для случая, описанного в этой статье: http://msdn.microsoft.com/en-us/library/b05d59ty.aspxПоэтому, если вас интересует свойство Chars для значения типа string, используйте его, но оно не работает для большинства интересующих меня массивов, включая, я почти уверен, массив строк из исходного вопроса.
Вы можете преобразовать индексатор в IEnumerable
public static IEnumerable<T> AsEnumerable<T>(this object o) where T : class {
var list = new List<T>();
System.Reflection.PropertyInfo indexerProperty = null;
foreach (System.Reflection.PropertyInfo pi in o.GetType().GetProperties()) {
if (pi.GetIndexParameters().Length > 0) {
indexerProperty = pi;
break;
}
}
if (indexerProperty.IsNotNull()) {
var len = o.GetPropertyValue<int>("Length");
for (int i = 0; i < len; i++) {
var item = indexerProperty.GetValue(o, new object[]{i});
if (item.IsNotNull()) {
var itemObject = item as T;
if (itemObject.IsNotNull()) {
list.Add(itemObject);
}
}
}
}
return list;
}
public static bool IsNotNull(this object o) {
return o != null;
}
public static T GetPropertyValue<T>(this object source, string property) {
if (source == null)
throw new ArgumentNullException("source");
var sourceType = source.GetType();
var sourceProperties = sourceType.GetProperties();
var properties = sourceProperties
.Where(s => s.Name.Equals(property));
if (properties.Count() == 0) {
sourceProperties = sourceType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic);
properties = sourceProperties.Where(s => s.Name.Equals(property));
}
if (properties.Count() > 0) {
var propertyValue = properties
.Select(s => s.GetValue(source, null))
.FirstOrDefault();
return propertyValue != null ? (T)propertyValue : default(T);
}
return default(T);
}