识别“;动作”;(将分配哪些属性);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"
}
}
}
您无法查看以某种内置方式更改了什么,因为更改的内容与实例的当前状态有关。示例:
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表达式无法由编译器自动转换为表达式树,因此每次调用需要将表达式约束为一个属性
此外,带有赋值运算符的表达式树也不能自动转换,因此您必须找到其他方法。