Passing a type created in Runtime for a statistical method

Asked

Viewed 121 times

1

EDIT

My problem is this.

I need to generate a lambda expression that is of a type that I will only know at the time of execution, IE, the type to be used will be passed in the parameter classType of the controller below. But the type I create in the Runtime method is not compatible with the expression I need to create.

NOTE: The Whereequalsnontyped method recognizes the type of the generated context, but when using typeof() it returns the type 'System.Object'.

Below is the controller calling the method to get the class type dynamically:

 [Route ("{classtype} / {id} / {key}")]
    public string GetObter (int id, string key, string classtype)
    {
        var attach = servico.ObterDinamico (classtype, id, includes);
        return attach.RetrieveFiles (key);
    }
}

Method that creates context from the past type:

public object ObterDinamico(string typeName, int id, string [] includes = null)
    {
        Type tableEntity = Type.GetType ("My_Domain." + TypeName + ", My_Domain");

        IEnumerable <dynamic> dbObject = (IEnumerable <dynamic>)
                            typeof (DbContext) .GetMethod ("Set", Type.EmptyTypes)
                            .MakeGenericMethod (tableEntity)
                            .Invoke (bd, null);
        IQueryable <dynamic> result = dbObject.AsQueryable ();
        if (includes! = null)
            foreach (string i in includes)
                result = result.Include (i);
        return result.WhereEqualsNonTyped ("id", id, typeName);
    }

lambda method that does not recognize the type T in this case, so does not generate the expression as accurate:

public static IQueryable <T> WhereEqualsNonTyped <T> (this IQueryable <T> query, string propertyName, dynamic value, string typeName)
{
    try
    {
        //sem essa instancia do Type para gerar o tipo dinâmico que preciso 
        //o método sempre dá erro assim que chega na linha 
        //MemberExpression
        var type = Type.GetType ("My_Domain." + typeName + ", My_Domain");
        ParameterExpression parameter = Expression.Parameter (type, "type");
        MemberExpression property = Expression.Property (parameter, propertyName);
        BinaryExpression expression = Expression.Equal (property, Expression.Constant (value, value.GetType ()));
        Expression <Func <T, bool >> predicate = Expression.Lambda <Func <T, bool >> (expression, parameter);
        return query.Where (predicate);
    }
    catch (Exception e)
    {
        return query;
    }
}

Currently the error that is generated is:

Parameterexpression of type 'My_domain.my_object' cannot be used to delegate the System.Object type parameter'

  • Whereequals is the problem?

  • That, the Get method accesses setClass and creates an instance of the object at runtime. However, when the Whereequals class is going to be executed, it cannot access the dynamic class created at runtime by accessing an instance of the Object class.

  • And when going to perform the search for the generic attribute passed is generated the inaccessible attribute error. And the lambda expression is not generated.

  • Has a code that is not used in Get SetClass, has a code with dynamic which in my opinion will not work either, maybe the problems are before, but, failed to say what the mistake, have to put in question?

  • if (!string.IsNullOrEmpty(classType)) SetClass(classType); what does this code do? and IQueryable<dynamic> result = model?.AsQueryable(); here is also wrong, where is it used and why did you do so? Reminder: the only correct code is public static IQueryable<T> WhereEquals<T> this is right, it is unnecessary because with the expressions already has this, but, it is correct!

  • The setClass takes a string and creates an object instance through the string that is passed, so far so good. Iqueryable<Dynamic> result = model?. Asqueryable(). This section does the following, after generating the instance of.

  • I don’t know the general context, but maybe that’s what’s missing, the way it’s still giving doubts about the other methods implemented! still explain more in question, put all the code is already a good start.

  • I updated the question to clarify the problem.

  • So you did an extension method, so why instantiate a class that comes from the method itself? has sausage in your code, from a checked that is not valid... !!!

  • Only then the code already works: as the code should be https://ideone.com/jnDd7p (just look at the code the error of the site is normal)

  • This part I put to check if the object I want was being generated correctly, because when I access the Whereequals method it loses the reference of the object and it becomes an instance of the 'System.Object'. It was bad, my mistake not having explained why of is generating again in the Whereequals method.

  • So, I tested only the extension method in a code of its own and it works, the problem is not Whereequals is the previous method that in my view the two are unnecessary, where to use it?

  • @Virgilionovic when the object type is well specified in the class that calls the Whereequals method it works well, the problem only occurs when I have to generate the object instance in Runtime, as in the example. Because the method cannot identify this dynamic object.

  • William If the object you want to generate isn’t in the context class it won’t work, your code is unnecessary without having a clearer need, see, I’m trying to show you that what you’re doing is bad practice, because so far it has not shown me a functional point and where it will use and for what need, is an object of the ORM class, it must exist if it causes no errors.

  • @Virgilionovic, let’s start with my need for this method. I have several objects that act as "combos", that is, they are composed only by name and id, and in the other variable. And instead of generating various contexts that act to perform the research of each of these objects, this method was built for this. But in the Get method where it is instantiated I found the following problem: the whereEquals method fails to identify the type of iqueryable that is generated in Runtime.

  • the error is clear IQueryable de dynamic is a layer Entity Frameworkthat needs a definite type will not work! already begins the problem there, about contexts, maybe there are better ways to do this and for sure exists.

  • @Virgilionovic updated the question, now it contains all the methods used.

  • Look maybe like this public static dynamic GetInstance change to public static T GetInstance<T> and on the last line return Activator.CreateInstance<T>(Type.GetType(fullName)); already change this well to a Generic object that must be contained in its ORM class. I took another look generated , if you are repeating too much code can summarize all this, but, it is a general way maybe this modification helps you

  • @Virgilionovic I would do that, but the way I want the method to work it becomes unfeasible. Because the type T will be known at the time of execution, it comes as a front end parameter. From this I have to generate an instance of this object and perform the search.

  • I really can’t understand you, because now the kind of data comes from Front-End strange this, but, as there is no way to move because it is a local problem and without reproduction is complicated in me help you, sorry!

  • In fact the type of combo to be worked always came from the front, but I did not find it necessary to pass this part here. That’s why I have to access the Whereequals method as much as possible. But I appreciate the help already.

  • @Virgilionovic managed to solve the problem in a simple way. Thanks for the help.

Show 17 more comments

1 answer

0


PROBLEM SOLVED

I managed to solve my problem in a very simple way, after some extensive researches I saw that my problem was actually to pass a dynamic type generated in Runtime, to a static method. And I was able to solve it through reflection.

Below follows my problem solved:

Controller que chama o método obterDinamico:
        [Route("{classtype}/{id}/{key}")]
        public string GetObter(int id, string key, string classtype)
        {
            var attach = servico.ObterDinamico(classtype, id, includes);
            return attach.RetrieveFiles(key);
        }

The solution of the problem, was carried out in the method to obtain all:

       public object ObterDinamico(string typeName, int id, string[] includes = null)
        {
            Type tableEntity = Type.GetType("My_Domain." + typeName + ", My_Domain");
            IQueryable<dynamic> dbObject = (IQueryable<dynamic>)
                                typeof(DbContext).GetMethod("Set", Type.EmptyTypes)
                                .MakeGenericMethod(tableEntity)
                                .Invoke(bd, null);
            IQueryable<dynamic> result = dbObject.AsQueryable();
//Chamo os metodos que preciso através da reflexão e com isso ele é instanciado com o tipo do objeto que é criado em runtime. Com isso meu problema foi resolvido
            MethodInfo notExcludeMethodInfo = typeof(ReflectionHelper).GetMethod("NaoExcluidos", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(tableEntity);
            MethodInfo whereEqualsMethodInfo = typeof(ReflectionHelper).GetMethod("WhereEquals", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(tableEntity);
            if (includes != null)
                foreach (string i in includes)
                    result = result.Include(i);
            result = (IQueryable<dynamic>)notExcludeMethodInfo.Invoke(null, new object[] { result });
            result = (IQueryable<dynamic>)whereEqualsMethodInfo.Invoke(null, new object[] { result, "id", id });
            return result.FirstOrDefault();
        }

One of the methods that are instantiated through reflection:

public static IQueryable<T> WhereEquals<T>(this IQueryable<T> query, string propertyName, dynamic value)
        {
            try
            {
                ParameterExpression parameter = Expression.Parameter(typeof(T), "type");
                MemberExpression property = Expression.Property(parameter, propertyName);
                BinaryExpression expressao = Expression.Equal(property, Expression.Constant(value, value.GetType()));
                Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(expressao, parameter);
                return query.Where(predicate);
            }
            catch (Exception e)
            {
                return query;
            }
        }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.