我决定重新制作帖子,因为我之前的帖子没有正确完成它应该做的事情。
要检查对象上的索引器,您可以使用以下命令,这将
- 当对象为空时返回空
- 未找到索引器时返回空 IList
- 返回带有找到的索引器的 MethodInfo 列表
检查它的技巧是检查一个属性是否有任何GetIndexParameters();
public IList<MethodInfo> GetIndexProperties(object obj)
{
if (obj == null)
{
return null;
}
var type = obj.GetType();
IList<MethodInfo> results = new List<MethodInfo>();
try
{
var props = type.GetProperties(System.Reflection.BindingFlags.Default |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance);
if (props != null)
{
foreach (var prop in props)
{
var indexParameters = prop.GetIndexParameters();
if (indexParameters == null || indexParameters.Length == 0)
{
continue;
}
var getMethod = prop.GetGetMethod();
if (getMethod == null)
{
continue;
}
results.Add(getMethod);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return results;
}
这适用于列表、字典、字符串、带有索引器的对象、使用 IndexerNameAttribute 定义的索引器
作为一个例子,我使用了这个 MainMethod,尝试了几种可能性
object[] exampleHayStack = new object[] {
"This is a test of an indexer",
new TestIndexer(),
null,
string.Empty,
new ClassIndexer(),
new Dictionary<string, string>() { { "key", "value" } },
new List<string>() { "A", "B", "C", "D", "E", "F", "G" } };
ClassIndexer myIndexer = new ClassIndexer();
foreach (var obj in exampleHayStack)
{
var methods = myIndexer.GetIndexProperties(obj);
if (methods == null || methods.Count == 0)
{
Console.WriteLine("{0} doesn't have any indexers", obj);
continue;
}
Console.WriteLine("Testing {0}", obj);
foreach (MethodInfo mi in methods)
{
IList<object> indexParams = new List<object>();
var requiredParams = mi.GetParameters();
foreach (var par in requiredParams)
{
indexParams.Add(myIndexer.ParamForObject(obj, par));
}
try
{
var result = mi.Invoke(obj, indexParams.ToArray());
Console.WriteLine("Result of requesting ({0}) = {1}", string.Join(",", indexParams), result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Console.ReadLine();
然后导致:
Testing This is a test of an indexer
Result of requesting (21) = i
Testing TestReflection.Program+TestIndexer
Result of requesting (53) = 5
Result of requesting (Key) = Key item
doesn't have any indexers
Testing
Exception has been thrown by the target of an invocation.
TestReflection.Program+ClassIndexer doesn't have any indexers
Testing System.Collections.Generic.Dictionary`2[System.String,System.String]
Result of requesting (key) = value
Testing System.Collections.Generic.List`1[System.String]
Result of requesting (5) = F
你可以在这里找到 ClassIndexer 的完整实现,它包含一个额外的方法来获取可能的键值(但你已经拥有了)
public class ClassIndexer
{
Random pNext = new Random();
public IList<MethodInfo> GetIndexProperties(object obj)
{
if (obj == null)
{
return null;
}
var type = obj.GetType();
IList<MethodInfo> results = new List<MethodInfo>();
try
{
var props = type.GetProperties(System.Reflection.BindingFlags.Default |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance);
if (props != null)
{
foreach (var prop in props)
{
var indexParameters = prop.GetIndexParameters();
if (indexParameters == null || indexParameters.Length == 0)
{
continue;
}
var getMethod = prop.GetGetMethod();
if (getMethod == null)
{
continue;
}
results.Add(getMethod);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return results;
}
public object ParamForObject(object obj, ParameterInfo pi)
{
if (obj is IDictionary)
{
int maxNumber = ((IDictionary)obj).Keys.Count;
if (pi.ParameterType.Equals(typeof(int)))
{
return pNext.Next(maxNumber);
}
if (pi.ParameterType.Equals(typeof(string)))
{
int target = pNext.Next(maxNumber);
foreach (var key in ((IDictionary)obj).Keys)
{
target--;
if (target <= 0)
{
return key;
}
}
return null;
}
}
if (obj is string)
{
if (pi.ParameterType.Equals(typeof(int)))
{
return pNext.Next((obj as string).Length);
}
}
if (obj is IList)
{
return pNext.Next(((IList)obj).Count);
}
if (pi.ParameterType.Equals(typeof(string)))
{
return "Key";
}
if (pi.ParameterType.Equals(typeof(int)))
{
return pNext.Next(100);
}
return null;
}
public ClassIndexer()
{
}
}
对于其余的,这是一项很好的研究,感谢您的提问!