使用动态Lambda表达式时如何模拟/拦截类型?

时间:2018-11-21 11:11:57

标签: c# lambda types dynamic-linq

我真的很喜欢动态Lambda表达式,即从字符串中构建一个可与Linq方法一起使用的lambda谓词。我可以看到将来的用途。

我想知道是否可以模拟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 class吗?

0 个答案:

没有答案