我定义了一个接口和一个类如下
public interface IXmlKey
{
string Name { get; set; }
string Value { get; set; }
bool HasChildren { get; set; }
}
public interface IXmlKey<T> : IXmlKey where T : IXmlKey<T>
{
public T[] Children { get; set; }
}
以及方法、代码
private static bool ReadSubXmlKeys(XmlReader subReader, IXmlKey objInstance, bool hasChildren, out string error)
{
error = null;
var childrenProp = objInstance.GetType().GetProperties().Single(p => p.Name.Equals("Children"));
var childType = childrenProp.PropertyType.GetElementType();
var childPis = childType.GetProperties();
var generateList = typeof(List<>).MakeGenericType(childType);
var childrenList = Activator.CreateInstance(generateList);
var childrenListType = childrenList.GetType();
//public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
var fun = typeof(Func<,>).MakeGenericType(childType, typeof(bool));
var anyMethod = typeof(Enumerable).GetMethodWithLinq("Any", typeof(IEnumerable<>), typeof(Func<,>)).MakeGenericMethod(childType);
var startNodeName = objInstance.Name;
do
{
var nodeName = subReader.Name;
//var isExist = anyMethod.Invoke(null, [childrenList, <what here>]); ---> here
}
while (subReader.Read());
return true;
}
如您所见,我不确定调用 List.Any(t => t.Name.Equals(nodeName )) 的正确参数是什么,其中 T : IXmlKey
请帮忙。
您需要传递
Func<childType,bool>
谓词。
拥有它的实例的一种方法是动态构建一个表达式并像这样编译它:
...
var anyMethod = typeof(Enumerable).GetMethodWithLinq("Any", typeof(IEnumerable<>), typeof(Func<,>)).MakeGenericMethod(childType);
...
var captureClass = new Capture { Name = "example" }; // mimic c# compiler to compile once
var parameterExpression = Expression.Parameter(childType, "t");
var propertyInfo = childType.GetProperty(nameof(IXmlKey.Name));
var propertyCall = Expression.Property(parameterExpression, propertyInfo);
var fieldAccess = Expression.Field(Expression.Constant(captureClass, typeof(Capture)), nameof(Capture.Name));
var equalsMethod = typeof(string).GetMethod("Equals", [typeof(string)]);
var expCall = Expression.Call(propertyCall, equalsMethod, fieldAccess);
var lambda = Expression.Lambda(expCall, [parameterExpression]);
var compiledPredicate = lambda.Compile();
...
do
{
captureClass.Name = subReader.Name;
var isExist = anyMethod.Invoke(null, [childrenList, compiledPredicate]);
}
while (subReader.Read());
return true;
为了优化,你也需要这个类:
public class Capture {
public string Name;
}