![](/img/trans.png)
[英]How do you get the all properties of a class and its base classes (up the hierarchy) with Reflection? (C#)
[英]C# Reflection: Get info for all members of class and base classes
當我運行以下代碼時,它只返回MethodInfo
/ FieldInfo
/etc。 直接屬於我在其中搜索信息對象的Type
。我如何找到信息對象,而不管它駐留在基類中並且可能是私有的?
obj.GetType().GetMethod(methodName, bindingFlags);
好吧,你回答了你自己的問題,但據我所知,你的主要要求是How do I find the info object regardless of where it is found in the hierarchy?
此處不需要遞歸來獲取完整層次結構中的所有成員。 您可以在Type
上使用GetMembers
函數,它將返回包括所有基類在內的所有成員。
下一個代碼示例演示了這一點:
var names =
typeof(MyClass).GetMembers()
.Select (x => x.Name);
Console.WriteLine (string.Join(Environment.NewLine, names));
對於這樣的結構
class MyClass : Base
{
public string Name { get; set; }
public string Surname { get; set; }
}
class Base
{
public string Name { get; set; }
}
返回
get_Name
set_Name
get_Surname
set_Surname
get_Name
set_Name
ToString
Equals
GetHashCode
GetType
.ctor
Name
Surname
請注意,用於自動屬性的get_Name
訪問器出現了兩次,因為MyClass
隱藏了基類的Name
屬性。 還要注意object
類中定義的ToString
、 GetType
等方法
如果在子類中找不到 info 對象,以下代碼將查看對象的每個基類。 需要注意的是,雖然它會返回基類信息的對象,它將返回的對象,它“運行到第一個”,所以如果你有一個變量叫_blah
在你的子類和可變稱為_blah
基類,那么_blah
將從子類返回。
public static MethodInfo GetMethodInfo(this Type objType, string methodName, BindingFlags flags, bool isFirstTypeChecked = true)
{
MethodInfo methodInfo = objType.GetMethod(methodName, flags);
if (methodInfo == null && objType.BaseType != null)
{
methodInfo = objType.BaseType.GetMethodInfo(methodName, flags, false);
}
if (methodInfo == null && isFirstTypeChecked)
{
throw new MissingMethodException(String.Format("Method {0}.{1} could not be found with the following BindingFlags: {2}", objType.ReflectedType.FullName, methodName, flags.ToString()));
}
return methodInfo;
}
public static FieldInfo GetFieldInfo(this Type objType, string fieldName, BindingFlags flags, bool isFirstTypeChecked = true)
{
FieldInfo fieldInfo = objType.GetField(fieldName, flags);
if (fieldInfo == null && objType.BaseType != null)
{
fieldInfo = objType.BaseType.GetFieldInfo(fieldName, flags, false);
}
if (fieldInfo == null && isFirstTypeChecked)
{
throw new MissingFieldException(String.Format("Field {0}.{1} could not be found with the following BindingFlags: {2}", objType.ReflectedType.FullName, fieldName, flags.ToString()));
}
return fieldInfo;
}
我改變了 bsara 的實現,以便能夠找到私有成員。
我像這樣使用它:
public static void Save(string filename, object obj)
{
try
{
using Stream s = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None);
var b = new BinaryFormatter();
b.Serialize(s, obj);
}
catch(SerializationException e)
{
var type= e.Message.Split("in Assembly")[0].Replace("Type", string.Empty).Replace("'", string.Empty).Trim();
var assembly=e.Message.Split("in Assembly")[1].Split("'")[1];
var atype= Type.GetType(type);
string path = FindObject(new Stack<object>(new object[] { obj }), atype, "[myself]");
throw new SerializationException($"Could not serialize path {path} in {obj.GetType().Name} due to not being able to process {type} from {assembly}. see inner exception for details", e);
}
}
小更新的方法:
private static bool TrySerialize(object obj)
{
if(obj == null)
return true;
var stream = new MemoryStream();
var bf = new BinaryFormatter();
try
{
bf.Serialize(stream, obj);
}
catch(SerializationException)
{
return false;
}
return true;
}
private static string FindObject(Stack<object> self, Type typeToFind, string path)
{
var _self = self.Peek();
if(self.Where(x => x.Equals(_self)).Count() > 1) return null;
foreach(var prop in _self.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic).Where(x => !x.GetCustomAttributes(true).Any(y => y is XmlIgnoreAttribute)))
{
switch(prop.MemberType)
{
case System.Reflection.MemberTypes.Property:
{
var line = string.Format("{0}::{1}", path, prop.Name);
var _prop = prop as PropertyInfo;
if(_prop.GetIndexParameters().Count() > 0) break;
if(typeToFind.IsAssignableFrom(_prop.PropertyType))
return line;
if(_prop.PropertyType.IsPrimitive || _prop.PropertyType == typeof(DateTime) || _prop.PropertyType == typeof(string))
continue;
var subInst = _prop.GetValue(_self, new object[0]);
if(subInst == null)
continue;
if(!TrySerialize(subInst))
{
System.Diagnostics.Debugger.Log(0, "", string.Format("Cannot serialize {0}\n", line));
}
self.Push(subInst);
var result = FindObject(self, typeToFind, line);
self.Pop();
if(result != null)
return result;
}
break;
case System.Reflection.MemberTypes.Field:
{
var line = string.Format("{0}::*{1}", path, prop.Name);
var _prop = prop as FieldInfo;
if(typeToFind.IsAssignableFrom(_prop.FieldType))
return line;
if(_prop.FieldType.IsPrimitive || _prop.FieldType == typeof(DateTime) || _prop.FieldType == typeof(string))
continue;
var subInst = _prop.GetValue(_self);
if(subInst == null)
continue;
if(!TrySerialize(subInst))
{
System.Diagnostics.Debugger.Log(0, "", string.Format("Cannot serialize field {0}\n", line));
}
self.Push(subInst);
var result = FindObject(self, typeToFind, line);
self.Pop();
if(result != null)
return result;
}
break;
case System.Reflection.MemberTypes.Event:
{
var line = string.Format("{0}::!{1}", path, prop.Name);
var _prop = prop as EventInfo;
if(typeToFind.IsAssignableFrom(_prop.EventHandlerType))
return line;
var field = _self.GetType().GetField(_prop.Name,
BindingFlags.NonPublic |BindingFlags.Instance |BindingFlags.GetField);
if(field != null && !field.GetCustomAttributes(true).Any(x => x is NonSerializedAttribute) && !TrySerialize(field.GetValue(_self)))
{
System.Diagnostics.Debugger.Log(0, "", string.Format("Cannot serialize event {0}\n", line));
}
}
break;
case System.Reflection.MemberTypes.Custom:
{
}
break;
default: break;
}
}
if(_self is IEnumerable)
{
var list = (_self as IEnumerable).Cast<object>();
var index = 0;
foreach(var item in list)
{
index++;
self.Push(item);
var result = FindObject(self, typeToFind, string.Format("{0}[{1}]", path, index));
self.Pop();
if(result != null)
return result;
}
}
return null;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.