Мне очень нравятся динамические лямбда-выражения, то есть создание из строки лямбда-предиката для использования с методами Linq.Я могу видеть будущее использование для этого.
Мне было интересно, можно ли поиграть в Type.В качестве первого шага я вывел класс из System.Type, чтобы я мог размещать точки останова, чтобы увидеть, что называется.Я предоставил, как мне кажется, сквозную реализацию, но она не планируется.
Я получаю сообщение об ошибке Specified method is not supported
в строке
var e = myAlias.DynamicExpression.ParseLambda(paramExps, null, expression);
, хотя могу видетьэто проходит через правильную информацию о методе.Мой «контроль над экспериментом» - это стандарт typeof(Class1)
, который отлично работает.Вы можете увидеть это, попарно (не) комментируя
//Type paramtype = typeof(Class1);
Type paramtype = new MyType() ;
Вот полный список из консольного приложения.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using myAlias = System.Linq.Dynamic; //install-package 'System.Linq.Dynamic' v.1.0.7 with NuGet
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Class1> myList = new List<Class1>();
for (int i = 0; i < 10; i++)
{
Class1 obj1 = new Class1();
obj1.SetFoo(i);
Debug.Assert(obj1.Foo() == i);
myList.Add(obj1);
}
string expression = "o.Foo()<5";
/*
* STACK OVERFLOWERS: switch the following two lines (uncomment one, comment other)
*/
//Type paramtype = typeof(Class1);
Type paramtype = new MyType() ;
ParameterExpression[] paramExps = null;
{
List<ParameterExpression> pList = new List<ParameterExpression>();
var p = Expression.Parameter(paramtype, "o");
pList.Add(p);
paramExps = pList.ToArray();
}
var e = myAlias.DynamicExpression.ParseLambda(paramExps, null, expression);
Delegate compiled = e.Compile();
System.Func<Class1, bool> pred = (System.Func<Class1, bool>)compiled;
List<Class1> newList = new List<Class1>();
newList = (List<Class1>)myList.Where(pred).ToList();
}
}
class MyType : System.Type
{
public string myElementType = null;
Type typClass1 = typeof(Class1);
public override Guid GUID => typClass1.GUID;
public override Module Module => typClass1.Module;
public override Assembly Assembly => typClass1.Assembly;
public override string FullName => typClass1.FullName;
public override string Namespace => typClass1.Namespace;
public override string AssemblyQualifiedName => typClass1.AssemblyQualifiedName;
public override Type BaseType => typClass1.BaseType;
public override Type UnderlyingSystemType => typClass1.UnderlyingSystemType;
public override string Name => typClass1.Name;
public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => typClass1.GetConstructors(bindingAttr);
public override object[] GetCustomAttributes(bool inherit) => typClass1.GetCustomAttributes(inherit);
public override object[] GetCustomAttributes(Type attributeType, bool inherit) => typClass1.GetCustomAttributes(attributeType, inherit);
public override Type GetElementType() => typClass1.GetElementType();
public override EventInfo GetEvent(string name, BindingFlags bindingAttr) => typClass1.GetEvent(name, bindingAttr);
public override EventInfo[] GetEvents(BindingFlags bindingAttr) => typClass1.GetEvents(bindingAttr);
public override FieldInfo GetField(string name, BindingFlags bindingAttr) => typClass1.GetField(name, bindingAttr);
public override FieldInfo[] GetFields(BindingFlags bindingAttr) => typClass1.GetFields(bindingAttr);
public override Type GetInterface(string name, bool ignoreCase) => typClass1.GetInterface(name, ignoreCase);
public override Type[] GetInterfaces() => typClass1.GetInterfaces();
public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => typClass1.GetMembers(bindingAttr);
public override MethodInfo[] GetMethods(BindingFlags bindingAttr) => typClass1.GetMethods(bindingAttr);
public override Type GetNestedType(string name, BindingFlags bindingAttr) => typClass1.GetNestedType(name, bindingAttr);
public override Type[] GetNestedTypes(BindingFlags bindingAttr) => typClass1.GetNestedTypes(bindingAttr);
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => typClass1.GetProperties(bindingAttr);
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
return typClass1.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}
public override bool IsDefined(Type attributeType, bool inherit) => typClass1.IsDefined(attributeType, inherit);
protected override TypeAttributes GetAttributeFlagsImpl() => typClass1.Attributes;
protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
return typClass1.GetConstructor(bindingAttr, binder, callConvention, types, modifiers);
}
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
return base.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
}
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
return typClass1.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}
//https://docs.microsoft.com/en-us/dotnet/api/system.type.haselementtypeimpl?view=netframework-4.7.2
protected override bool HasElementTypeImpl() => typClass1.IsArray || typClass1.IsByRef || typClass1.IsPointer;
protected override bool IsArrayImpl() => typClass1.IsArray;
protected override bool IsByRefImpl() => typClass1.IsByRef;
protected override bool IsCOMObjectImpl() => typClass1.IsCOMObject;
protected override bool IsPointerImpl() => typClass1.IsPointer;
protected override bool IsPrimitiveImpl() => typClass1.IsPrimitive;
}
class Class1
{
private int mlFoo = 0;
public int Foo()
{
return mlFoo;
}
public void SetFoo(int rhs)
{
mlFoo = rhs;
}
}
}
Так что я хотел бы устранить эту ошибку и получитьмой проход через класс Type работает.Должен ли я перейти на класс TypeDelegator ?