1 Востаннє редагувалося Betterthanyou (13.12.2022 21:02:36)

Тема: params Expression<Func<T, object>>[] fxns передати заокруглені па.....

Потрібно передати в метод "f" заокругленні параметри до двох символів після крапки.

Не можна змінювати сам метод "f" і список listA, який передається як параметр

using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

public class A
{
    public double b { get; set; }
}

public class HelloWorld
{
    static string GetName2(MemberExpression member)
    {
        var fieldInfo = member.Member as FieldInfo;
        if (fieldInfo != null)
        {
            var d = fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (d != null) return d.Description;
            return fieldInfo.Name;
        }

        var propertInfo = member.Member as PropertyInfo;
        if (propertInfo != null)
        {
            var d = propertInfo.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (d != null) return d.Description;
            return propertInfo.Name;
        }

        return "?-?";
    }
    static string GetName<T>(Expression<Func<T, object>> expr)
    {
        var member = expr.Body as MemberExpression;
        if (member != null)
            return GetName2(member);

        var unary = expr.Body as UnaryExpression;
        if (unary != null)
            return GetName2((MemberExpression)unary.Operand);

        return "?+?";
    }
    public static void f<T>(IEnumerable<T> list, params Expression<Func<T, object>>[] fxns)
    {
        foreach (var fxn in fxns)
        {
            Console.WriteLine("fxn = " + GetName(fxn));
        }
        foreach (var item in list)
        {
            foreach (var fxn in fxns)
            {
                object ob = fxn.Compile()(item);
                Console.WriteLine("fxn2 = " + ob.ToString());
            }
        }

    }
    public static void Main(string[] args)
    {
        A a = new A();
        a.b = 9.123456789;

        List<A> listA = new List<A>();
        listA.Add(a);

        f<A>(
            listA, x => x.b
        );
    }
}

Я пробував так:
1)

        f<A>(
            listA,
            x =>
            {
                var c = Math.Round(x.b, 2);
                return (object)c;
            }
        );

Помилка (синтаксична): A lambda expression with a statement body cannot be converted to an expression tree

2) Та так

f<A>(listA, x => Math.Round(x.b, 2));

Помилка (під час виконання): Unable to cast object of type 'System.Linq.Expressions.MethodCallExpression1' to type 'System.Linq.Expressions.MemberExpression'.'


Без копіювання

Ще можна зробити копію listA і передати, але я намагаюся знайти інший варіант.

Як правильно передати метод Math.Round для заокруглення числа "b" ? (Чи таке взагалі можливо ?)

Подякували: leofun011

2

Re: params Expression<Func<T, object>>[] fxns передати заокруглені па.....

Math.Round(число чи змінна, кількість розрядів);
через кому

3

Re: params Expression<Func<T, object>>[] fxns передати заокруглені па.....

крапку цей метод не сприймає, тому що він розпізнає х.b як число х - до крапки, b - після крапки, і не може у ньому знайти цифри

4

Re: params Expression<Func<T, object>>[] fxns передати заокруглені па.....

PeSePol написав:

Math.Round(число чи змінна, кількість розрядів);
через кому

так не працює, помилка
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.MethodCallExpression2' to type 'System.Linq.Expressions.MemberExpression'.

мені потрібно записати це як лямда вираз, а не просто викликати Math.Round

Подивіться які параметри приймає "f" метод

public static void f<T>(IEnumerable<T> list, params Expression<Func<T, object>>[] fxns)
Подякували: leofun011

5

Re: params Expression<Func<T, object>>[] fxns передати заокруглені па.....

ви можете зробити тавтологію, якщо не хочете міняти назви змінних

f<A>(
            listA,
            x =>
            {
                var c = x.b;
                var c = Math.Round(с, 2);
                return (object)c;
            }
            );

але краще змінити назви

6

Re: params Expression<Func<T, object>>[] fxns передати заокруглені па.....

Betterthanyou написав:

Потрібно передати в метод "f" заокругленні параметри до двох символів після крапки.

Я пробував так:

f<A>(listA, x => Math.Round(x.b, 2));

Помилка (під час виконання): Unable to cast object of type 'System.Linq.Expressions.MethodCallExpression1' to type 'System.Linq.Expressions.MemberExpression'.'

Як правильно передати метод Math.Round для заокруглення числа "b" ? (Чи таке взагалі можливо ?)

Якось так (зміни мінімальні) :

using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

public class A {
    [Description("Description should be here")]
    public double b { get; set; }
}

public class HelloWorld {
    static string GetName2(MemberExpression member) {
        var fieldInfo = member.Member as FieldInfo;
        if (fieldInfo != null) {
            var d = fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (d != null) return d.Description;
            return fieldInfo.Name;
        }
        var propertInfo = member.Member as PropertyInfo;
        if (propertInfo != null) {
            var d = propertInfo.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (d != null) return d.Description;
            return propertInfo.Name;
        }
        return "?-?";
    }
    static string GetName<T>(Expression<Func<T, object>> expr) {
        var member = expr.Body as MemberExpression;
        if (member != null)
            return GetName2(member);

        var unary = expr.Body as UnaryExpression;
        if (unary != null) {
            member = unary.Operand as MemberExpression;
            if (member != null)
                return GetName2(member);
            var method = unary.Operand as MethodCallExpression;
            if (method != null)
                foreach(var arg in method.Arguments) {
                    var m = arg as MemberExpression;
                    if (m != null)
                        return GetName2(m);
                }
        }

        return "?+?";
    }
    public static void f<T>(IEnumerable<T> list, params Expression<Func<T, object>>[] fxns) {
        foreach (var fxn in fxns) {
            Console.WriteLine("fn name : " + GetName(fxn));
        }
        foreach (var item in list) {
            foreach (var fxn in fxns) {
                object ob = fxn.Compile()(item);
                Console.WriteLine("fn eval = " + ob.ToString());
            }
        }
    }
    public static double CustomStaticMethod(double a, float b, double value, int c) {
        return Math.Round(value, 2);
    }
    public static void Main(string[] args) {
        List<A> listA = new List<A>() {
            new A() { b = 9.123456789d }
        };
        f<A>(
            listA,
            x => x.b,
            x => Math.Round(x.b, 2),
            x => CustomStaticMethod(2d, 3f, x.b, 5)
        );
        Console.ReadLine();
    }
}
Подякували: PeSePol, Betterthanyou2