C# 反射索引属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/291359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Reflection Indexed Properties
提问by Greg Finzer
I am writing a Clone method using reflection. How do I detect that a property is an indexed property using reflection? For example:
我正在使用反射编写 Clone 方法。如何使用反射检测属性是否为索引属性?例如:
public string[] Items
{
get;
set;
}
My method so far:
到目前为止我的方法:
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;
}
采纳答案by FlySwat
if (propertyInfo.GetIndexParameters().Length > 0)
{
// Property is an indexer
}
回答by Jeromy Irvine
What you want is the GetIndexParameters()
method. If the array that it returns has more than 0 items, that means it's an indexed property.
你要的是GetIndexParameters()
方法。如果它返回的数组有 0 个以上的项目,这意味着它是一个索引属性。
See the MSDN documentationfor more details.
有关更多详细信息,请参阅MSDN 文档。
回答by Jeromy Irvine
Sorry, but
对不起,可是
public string[] Items { get; set; }
is notan indexed property, it's merely of an array type! However the following is:
是不是索引属性,它只是一个数组类型的!然而,以下是:
public string this[int index]
{
get { ... }
set { ... }
}
回答by ILIA BROUDNO
Here is some code that worked for me:
这是一些对我有用的代码:
foreach (PropertyInfo property in obj.GetType().GetProperties()) { object value = property.GetValue(obj, null); if (value is object[]) { .... } }
P.S. .GetIndexParameters().Length > 0)
works for the case described in this article: http://msdn.microsoft.com/en-us/library/b05d59ty.aspxSo if you care about the property named Chars for a value of type string, use that, but it does not work for most of the arrays I was interested in, including, I am pretty sure, a string array from the original question.
PS .GetIndexParameters().Length > 0)
适用于本文中描述的案例:http: //msdn.microsoft.com/en-us/library/b05d59ty.aspx因此,如果您关心名为 Chars 的属性作为字符串类型的值,请使用它,但它不适用于我感兴趣的大多数数组,包括,我很确定,来自原始问题的字符串数组。
回答by John Holliday
If you call property.GetValue(obj,null)
, and the property IS indexed, then you will get a parameter count mismatch exception. Better to check whether the property is indexed using GetIndexParameters()
and then decide what to do.
如果您调用property.GetValue(obj,null)
,并且属性已被索引,那么您将收到参数计数不匹配异常。最好检查属性是否被索引使用GetIndexParameters()
,然后决定做什么。
回答by Krzysztof Radzimski
You can convert the indexer to IEnumerable
您可以将索引器转换为 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);
}