PostSharp 更改的字段定义对使用 lambda 表达式不友好
Field definitions changes by PostSharp not friendly to using lambda expressions
我正在使用 PostSharp 的 LocationInterceptionAspect
拦截对 class 的字段和属性的调用。很明显,PostSharp 在编译时更改了这样的 class。但是,它妨碍了我,问题不仅与依赖此功能的代码的优雅有关。
也就是说,我也使用lambda表达式来获取那些字段和属性的名称。这里有一个简化的例子来证明这一点:
namespace Example
{
using System.Linq.Expressions;
public class Data
{
public string Field;
public string Property { get; set; }
}
public class Process
{
public void Do()
{
string name1 = this.GetAttributeName<Data>(data => data.Field);
// name1 = "<Field>k_OriginalField"
string name2 = this.GetAttributeName<Data>(data => data.Property);
// name2 = "Property"
}
private string GetAttributeName<DECLARING_TYPE>(Expression<Func<DECLARING_TYPE, object>> expression)
{
return (expression.Body as MemberExpression)?.Member?.Name;
}
}
}
很明显:我希望“k_OriginalField”为 "Field"。这里有什么可以做的吗?
当然,我可以对这个字符串的格式做出一些假设并解析出我想要的值,但这对我来说似乎有点难看。不过,我确实需要保留字段定义并获取它们的名称(它们的用途比此处可见的要复杂得多)。我不确定 .NET 的 lambda 表达式构造在内部发生了什么,因为 Data.Field
显然存在(我也通过反汇编进行了验证),但它已更改为 属性,并且我猜猜我被交给了一个支持领域,我很困惑为什么。
感谢您的宝贵时间。
编辑:我弄清楚了为什么会这样(我之前忘记检查了):PostSharp 还更改了此 "field" 成员的用法(但我仍在质疑为什么),为此:
string name1 = this.GetAttributeName<Data>(data => data.<Field>k_OriginalField);
// name1 = "<Field>k_OriginalField"
我发现这种用法替换很奇怪,因为 PostSharp 的拦截方面的全部要点是重定向执行流(同时允许自定义执行控制),因此调整对这些更改的调用对我来说毫无意义。 Data
和 Process
class 都在同一个程序集中;也许将它们分开可以解决问题,但我不能轻易做到这一点,而且 - 再一次 - 作为解决方案看起来很难看。我希望 PostSharp 团队对此有话要说。
我不是 PostSharp 专家,但我认为在(大多数)一般情况下这不是一个可判定的问题。
想一想。 PostSharp 在构建时重写应用程序的部分类型系统,通过当时它可以执行的任何静态分析获知,对于那时可访问的所有相关程序集、版本和命名空间。
它无法看到未来并决定哪些候选重写应该被省略,因为客户端调用站点需要在稍后的时间点发生的构建中做出不同的假设,以及哪些会查看您的无需通过 PostSharp 镜头查看或使用不同镜头的相同类型系统。
这就是我认为的方式,它必须假设所有重写,当它被你的类型调用时,它被指示去做,必须在它们适用的任何地方以类型安全的方式得到尊重。
只是我的直觉。
'HTH,
我正在使用 PostSharp 的 LocationInterceptionAspect
拦截对 class 的字段和属性的调用。很明显,PostSharp 在编译时更改了这样的 class。但是,它妨碍了我,问题不仅与依赖此功能的代码的优雅有关。
也就是说,我也使用lambda表达式来获取那些字段和属性的名称。这里有一个简化的例子来证明这一点:
namespace Example
{
using System.Linq.Expressions;
public class Data
{
public string Field;
public string Property { get; set; }
}
public class Process
{
public void Do()
{
string name1 = this.GetAttributeName<Data>(data => data.Field);
// name1 = "<Field>k_OriginalField"
string name2 = this.GetAttributeName<Data>(data => data.Property);
// name2 = "Property"
}
private string GetAttributeName<DECLARING_TYPE>(Expression<Func<DECLARING_TYPE, object>> expression)
{
return (expression.Body as MemberExpression)?.Member?.Name;
}
}
}
很明显:我希望“
当然,我可以对这个字符串的格式做出一些假设并解析出我想要的值,但这对我来说似乎有点难看。不过,我确实需要保留字段定义并获取它们的名称(它们的用途比此处可见的要复杂得多)。我不确定 .NET 的 lambda 表达式构造在内部发生了什么,因为 Data.Field
显然存在(我也通过反汇编进行了验证),但它已更改为 属性,并且我猜猜我被交给了一个支持领域,我很困惑为什么。
感谢您的宝贵时间。
编辑:我弄清楚了为什么会这样(我之前忘记检查了):PostSharp 还更改了此 "field" 成员的用法(但我仍在质疑为什么),为此:
string name1 = this.GetAttributeName<Data>(data => data.<Field>k_OriginalField);
// name1 = "<Field>k_OriginalField"
我发现这种用法替换很奇怪,因为 PostSharp 的拦截方面的全部要点是重定向执行流(同时允许自定义执行控制),因此调整对这些更改的调用对我来说毫无意义。 Data
和 Process
class 都在同一个程序集中;也许将它们分开可以解决问题,但我不能轻易做到这一点,而且 - 再一次 - 作为解决方案看起来很难看。我希望 PostSharp 团队对此有话要说。
我不是 PostSharp 专家,但我认为在(大多数)一般情况下这不是一个可判定的问题。
想一想。 PostSharp 在构建时重写应用程序的部分类型系统,通过当时它可以执行的任何静态分析获知,对于那时可访问的所有相关程序集、版本和命名空间。
它无法看到未来并决定哪些候选重写应该被省略,因为客户端调用站点需要在稍后的时间点发生的构建中做出不同的假设,以及哪些会查看您的无需通过 PostSharp 镜头查看或使用不同镜头的相同类型系统。
这就是我认为的方式,它必须假设所有重写,当它被你的类型调用时,它被指示去做,必须在它们适用的任何地方以类型安全的方式得到尊重。
只是我的直觉。
'HTH,