Как смоделировать / перехватить тип при использовании динамического лямбда-выражения? - PullRequest
0 голосов
/ 21 ноября 2018

Мне очень нравятся динамические лямбда-выражения, то есть создание из строки лямбда-предиката для использования с методами 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 ?

...