识别“;动作”;(将分配哪些属性);T>;班

本文关键字:属性 gt 分配 动作 识别 | 更新日期: 2023-09-27 18:20:25

英语不是我的母语,我希望我能把我的问题说清楚。

我想知道如何在执行时识别Action类中包含的wich操作(确切地说,将调用wich属性)。

想象一下一个简单的员工类。。。

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

以及一个简单的Update()方法,该方法执行Action<>作为参数

public static void Update(Action<Employee> action) {
    //HERE : how could i know which properties will be assigned by analyzing the Action<Employee> object ?
    Employee em = new Employee();
    action(em);
    //Only FirstName and LastName have been assigned to "em"
}

Update方法可以这样调用:

//Call the Update method with only two "actions" : assign FirstName and LastName properties.
Update(e => { e.FirstName = "firstname"; e.LastName = "lastname"; });

我的问题是在Update()方法中确定哪些属性已"计划"用于Action<>中的赋值(以及相关值)对象

我如何通过分析Action来发现<>对象,则只有属性FirstName和LastName将被分配值"FirstName"answers"LastName"?有可能吗

我在谷歌和SO上找不到任何帮助。也许我问错了问题。

消息的末尾是可以执行/调试的整个程序。

提前感谢SO.上的每一个人

Mike

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestAction
{
    class Program
    {
        public class Employee
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public int Age { get; set; }
            public string Email { get; set; }
        }
        static void Main(string[] args)
        {
            //Call the Update method with only two "actions" : assign FirstName and LastName properties.
            Update(e => { e.FirstName = "firstname"; e.LastName = "lastname"; });
        }
        public static void Update(Action<Employee> action)
        {
            //HERE : how could i know which properties will be assigned by analyzing the Action<Employee> object ?
            Employee em = new Employee();
            action(em);
            //Only FirstName and LastName have been assigned to "em"
        }
    }
}

识别“;动作”;(将分配哪些属性);T>;班

您无法查看以某种内置方式更改了什么,因为更改的内容与实例的当前状态有关。示例:

A {Name="Patrick"} //init 
A {Name = "Jane"} // changed from Patrick to Jane
A {Name = "Martin"} //changed from Jane to Martin

所以,我不知道有其他的方式,自己管理这件事。跟踪所有属性设置器,当其中一个属性设置器被调用方设置为set时,将更改后的属性名称放入对象列表的某个本地实例中。

Update调用中,滚动更改的属性名称列表,只获取它们的值并更新它们(全部通过反射)。更新成功后,清除列表。

这只是一个想法,但也可以通过其他方式来实现。

这不是一个容易解决的问题,但如果您真的需要这样做,让我概述一下I知道如何做到这一点的方法。

分解和解释

这将涉及到获取一个.NET(或x86/x64)反汇编程序,该程序将在运行时运行,将其指向有问题的方法,然后分析输出,寻找对目标类型上字段的访问权限。

我想说这很难,你需要非常好地理解MSIL,以及编译器可能使用的优化技术,才能从这种技术中得到你想要的东西。

使用记录访问的代理对象

您可以创建一个代理对象,并将其传递给操作委托。该代理对象将记录每个属性被访问的情况,可能是在每个属性的布尔变量中。然后,您将查看这些布尔值,以确定访问了哪些属性。

这要容易得多,你需要使你的类是虚拟的,每个属性也是虚拟的,然后创建一个子类,你可以使用Reflection.Emit或其他方式在运行时创建类型。

但是需要实际执行操作委托所针对的方法中的所有代码,这可能是不需要的。

您也可以使用原始对象的常规副本,为每个属性赋予一些您知道操作委托不会赋予它的神奇值,调用委托,并检查神奇值和当前值之间的差异(在调用之后)。不幸的是,这还需要调用委托,并且还将在目标对象上执行任何属性设置程序,这两者都可能是不需要的。

我的看法

在我看来,你最好找到一种更明确的不同方式来做这件事。

感谢大家让我意识到无法分析代表(如果没有你们的解释,我仍然会想办法…)。

为了实现我想要做的事情,我需要通过一份财产分配清单的可能性,以及分析该清单的可能性。在你的帮助下,我得出了只有表达式树才能被分析的结论。我是这样做的:

public static void Update<T>(Expression<Action<T>> action) where T : class

在Update方法中,使用标准的Visitor模式分析表达式:我能够获得指定的属性和关联的值。

该方法被称为:

Update<Employee>(o => new Employee() { FirstName = "Mike", Email = "mike@so.com" });

再次感谢您的帮助!

Mike

您不能分析委托。要进行分析,您需要一个表达式树:

public static void Update(Expression<Action<Employee>> action)

不幸的是,带主体的lambda表达式无法由编译器自动转换为表达式树,因此每次调用需要将表达式约束为一个属性
此外,带有赋值运算符的表达式树也不能自动转换,因此您必须找到其他方法。