Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何编织C#代码来拦截对构造函数的调用?也许是自定义预处理器或Roslyn_C#_Preprocessor_Metaprogramming_Aop_Roslyn - Fatal编程技术网

如何编织C#代码来拦截对构造函数的调用?也许是自定义预处理器或Roslyn

如何编织C#代码来拦截对构造函数的调用?也许是自定义预处理器或Roslyn,c#,preprocessor,metaprogramming,aop,roslyn,C#,Preprocessor,Metaprogramming,Aop,Roslyn,有没有类似于[PostSharp]-[Infuse-C#的预编译器]的解决方案,可以让我在编译时修改代码 下面是一个伪代码 [InterceptCallToConstructors] void Method1(){ Person Eric = new Person("Eric Bush"); } InterceptCallToConstructors(ConstructorMethodArgs args){ if(args.Type == typeof(Person))

有没有类似于[PostSharp]-[Infuse-C#的预编译器]的解决方案,可以让我在编译时修改代码

下面是一个伪代码

[InterceptCallToConstructors]
void Method1(){
    Person Eric = new Person("Eric Bush");
}


InterceptCallToConstructors(ConstructorMethodArgs args){
    if(args.Type == typeof(Person))
        if(PersonInstances++ > 10 ) args.ReturnValue = null;
}
在本例中,我们看到,如果创建了10个以上的Person,则Eric不应包含新Person类

经过一些研究,我找到了两种解决方案,一种是PostSharp,另一种是Infuse。 使用Infuse很复杂,很难检测出有多少个人的实例,而PostSharp只需检测一行代码

我曾尝试使用PostSharp进行AOP,但PostSharp目前不支持拦截对构造函数方面的调用。
据我所知,Roslyn不支持在编译时修改代码

这将是一个“自定义预处理器”的答案,它修改源代码以实现OP的效果

我们的智能手机可以做到这一点

DMS提供源到源的转换,转换编码为

if you see *this*, replace it by *that*
这是以以下形式书写的:

rule xxx pattern_parameters
    this_pattern
    ->  that_pattern ;
“->”发音为“替换为::-}”

DMS在ASTs上运行,因此包括解析步骤(文本到ASTs)、树转换步骤和生成最终答案的预打印步骤(ASTs到文本)

OP似乎想要修改构造函数调用站点(他无法修改构造函数;无法使其返回“null”)。为了完成OP的任务,他将向DMS提供以下源到源转换规范:

       default domain CSharp~v5;  -- says we are working with C# syntax (and need the C# front end)

       rule intercept_constructor(c: IDENTIFIER, a:arguments): expression
           "  new \c (\a) "
       ->  "  \c.PersonInstances==10?null:(PersonInstances++,new \c (\a)) "
           if c == "Person";  -- one might want to force c to be on some qualified path
该规则所做的是找到任意形式的匹配构造函数调用语法,并将其替换为检查OP的前提条件的条件表达式,如果有太多的Person实例,则返回null(我们在这里修复了OP规范中的一个错误;无论是否创建了新Person实例,他似乎都会增加计数,这肯定不是他的意图).我们必须限定PersonInstance的位置;它不能只是在以太中漂浮。在本例中,我建议它是类的静态成员

详细信息:每个规则都有一个名称(“intercept\u constructor”,从OP偷来)。它指的是一个语法类型(“表达式”),语法形状为“new\c(\a),强制它只匹配作为表达式的构造函数调用。规则中的引号是元引号;它们将规则语言的语法与目标语言的语法(在本例中为C#)区分开来。反斜杠是元转义\元引号中的c与元引号外的c在规则中的思维方式相同,类似于\a


在一个非常大的系统中,可能有几个Person类。我们要确保我们得到了正确的答案;可能需要通过提供路径将引用的类限定为特定类。OP使用注释提示这一点。如果要检查包含方法上是否存在注释,则需要自定义特殊谓词来进行检查。DMS为编写这样的谓词提供了完整的工具,包括对AST的完全访问,因此谓词可以在搜索匹配注释时向上或向下爬升。

如果您在KRuntime(->ASP.NET 5)上运行,则可以通过实现

我建议你去:

  • aop

您是否试图以编程方式将“if(args…”复选框插入“Method1”中?(这是一种面向方面的编程)?@IraBaxter是的,必须以编程方式完成!如果您正在运行PostSharp,则在编译后修改代码。“在编译时”是什么意思你想在编译前对源代码进行修改吗?@ Irabxter你是对的。如果它是在编译或编译的时候就不重要了。我会编辑问题,如果我在我的代码库中看到这一点,我会对混淆感到非常恼怒。虽然它不是你的问题的答案,但是考虑清楚地调用静态工厂方法<代码。>CreatePerson处理此逻辑,而不是(实际上)定义自己的语言,恰巧看起来很像C#。当然,如果这正是你的目标,那也没关系。谢谢,但这还不包括创建了多少个人实例,我真的需要返回null。哎呀,我错过了一个细节;事实上规则中有几个愚蠢的错误;我发布这个answe时一定是深夜r、 我修正了这些愚蠢的事情,并修改了模式以增加计数(如果计数不太大)。原始版本和此版本,如果计数太大,都会返回null。请在您的问题中显示您希望得到的代码。我的确切目标是截获对构造函数的调用并处理返回值,不仅处理返回,而且完全控制返回r构造函数方法就像我在构造函数方法中一样。Postsharp MethodInterception完全满足我的要求,但不幸的是,它支持除调用构造函数之外的所有方法!我理解你的目标。你正在拒绝多个请求,以准确显示你期望的最终结果的代码。我声称我上面的规则可以做到这一点,直到你可以具体说明它是如何错误的。如果实例是在循环中生成的,它会计算实例吗?您建议的工具包是免费的还是试用的?