inversionhourglass / Rougamo

Compile-time AOP component. Works with any method, whether it is async or sync, instance or static. Uses an aspectj-like pattern to match methods.
MIT License
393 stars 47 forks source link

类库项目中,在Attribute中设置Pattern值,并将其添加到程序集中(在AssemblyInfo.cs文件中设置assembly值),编译报错。如果删除Pattern值,能够正常编译通过。 #66

Closed helloworld666 closed 6 months ago

helloworld666 commented 6 months ago

具体的异常信息如下: 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误 Fody: An unhandled exception occurred: Exception: Failed to execute weaver C:\Users\admin.nuget\packages\rougamo.fody\2.3.0\build..\weaver\Rougamo.Fody.dll Type: System.Exception StackTrace: 在 InnerWeaver.ExecuteWeavers() 位置 C:\projects\fody\FodyIsolated\InnerWeaver.cs:行号 219 在 InnerWeaver.Execute() 位置 C:\projects\fody\FodyIsolated\InnerWeaver.cs:行号 111 Source: FodyIsolated TargetSite: Void ExecuteWeavers() Transition is not a generic name 参数名: name Type: System.ArgumentException StackTrace: 在 Rougamo.Fody.Signature.SignatureParser.ShortGenericName(String name, Int32& genericCount) 在 Rougamo.Fody.Signature.SignatureParser.ParseType(TypeReference typeRef, List1 genericParameters, Dictionary2 genericMap) 在 System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() 在 System.Linq.Buffer1..ctor(IEnumerable1 source) 在 System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source) 在 Rougamo.Fody.Signature.SignatureParser.g__Impl|2_2(MethodDefinition methodDef, Boolean compositeAccessibility) 在 System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory) 在 Rougamo.Fody.ModelExtension.MatchMoPattern(RouMethod method, Mo mo, MoFrom from, Boolean compositeAccessibility) 在 System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() 在 Rougamo.Fody.RouMethod.AddMo(IEnumerable1 mos) 在 Rougamo.Fody.ModelExtension.Initialize(RouType rouType, MethodDefinition methdDef, CustomAttribute[] assemblyAttributes, TypeDefinition[] assemblyGenerics, RepulsionMo[] typeImplements, CustomAttribute[] typeAttributes, TypeDefinition[] typeGenerics, TypeDefinition[] typeProxies, CustomAttribute[] methodAttributes, TypeDefinition[] methodGenerics, TypeDefinition[] methodProxies, String[] assemblyIgnores, String[] typeIgnores, String[] methodIgnores, Boolean compositeAccessibility) 在 Rougamo.Fody.ModuleWeaver.FullScan() 在 Rougamo.Fody.ModuleWeaver.FindRous() 在 Rougamo.Fody.ModuleWeaver.Execute() 在 InnerWeaver.ExecuteWeavers() 位置 C:\projects\fody\FodyIsolated\InnerWeaver.cs:行号 196 Source: Rougamo.Fody

inversionhourglass commented 6 months ago

你的Pattern怎么写的

helloworld666 commented 6 months ago

您好。我的Pattern用的就是README中最简单的设置: public override string? Pattern => "method( .Get*(..))"; 以及它下面的其它几项设置,都会报同样的错误。取消Pattern 设置就能正确编译,并且也能实现方法织入。

inversionhourglass commented 6 months ago

你这个Pattern的格式不太对,跟README,第二段不能以.开头,不过你之前的报错似乎跟Pattern的内容无关。你搜一下你项目里Transition这个类,方便的话把这个类贴出来看一下,Rougamo似乎无法解析这个类型

helloworld666 commented 6 months ago

感谢回复。可能找打问题根源了,我的项目中引用了Stateless(5.15.0)组件 https://github.com/dotnet-state-machine/stateless ,并且在程序中有调用它的代码逻辑,我将这个组件及调用它的代码逻辑删除后,编译一切正常。如果把这个组件加回来,并且恢复调用它的代码逻辑则编译继续报错。

inversionhourglass commented 6 months ago

方便的话可以提供你现在使用Stateless的简化写法代码,我可以具体查查是什么情况,能够兼容使用最好

helloworld666 commented 6 months ago

public class JobStateMachine { private readonly StateMachine<JobStateEnum, JobTrigger> machine;

/// <summary>
/// 构造函数
/// </summary>
public JobStateMachine()
{
    //实例化状态机,并设置初始状态
    machine = new StateMachine<JobStateEnum, JobTrigger>(JobStateEnum.Idle);
    //状态转换完成后,更新设备对象的状态
    machine.OnTransitionCompleted((transition) => DeviceContext.Instance.State = transition.Destination);

    //当处于Idle状态时,如果点击Start按钮,则转换为Start状态,并在状态改变后,执行StartJob()方法
    machine.Configure(JobStateEnum.Idle)
        .Permit(JobTrigger.StartTrigger, JobStateEnum.Working)
        .OnExit(t => StartJob());
}

/// <summary>
/// 导出DOT Graph字符串
/// </summary>
/// <returns>DOT Graph字符串</returns>
public string ToDotGraph()
{
    return UmlDotGraph.Format(machine.GetInfo());
}

/// <summary>
/// 触发状态机的状态转换
/// </summary>
/// <param name="trigger">触发动作枚举</param>
public void TriggerState(JobTrigger trigger)
{
    machine.Fire(trigger);
}

/// <summary>
/// 启动作业处理
/// </summary>
private void StartJob()
{

}

}

helloworld666 commented 6 months ago

上面的代码,如果将: .OnExit(t => StartJob()) 这行代码,更改为: OnExit(t => {}) 编译就可以通过。JobStateEnum,JobTrigger分别是两个枚举类型。

public enum JobStateEnum { ///

/// 空闲 /// Idle, /// /// 工作中 /// Working, /// /// 暂停 /// Pause }

public enum JobTrigger { ///

/// 开始作业触发器 /// StartTrigger, /// /// 暂停作业触发器 /// PauseTrigger, /// /// 继续作业触发器 /// EndTrigger }

inversionhourglass commented 6 months ago

好的,感谢反馈,我研究一下

inversionhourglass commented 6 months ago

目前确定存在两个问题:

  1. 报错的根本原因是Rougamo对泛型嵌套类型的签名解析支持不到位;
  2. 关于OnExit(t => StartJob())会报错,但OnExit(t => {})正常。原因是前一种lambda写法在编译时会将lambda转换为当前类的一个方法,而后者在编译时会转换为当前类的一个嵌套类;两种方式生成出来的方法和类上都会标记[CompilerGenerated],Rougamo排除了编译器生成的类型,但没有排除编译器生成的方法。

上面两个问题都是需要解决的,Rougamo主要用于处理开发人员定义的方法,所以编译器生成的方法也是需要排除的。鉴于第一个问题可能需要些时间,所以稍后将会先发布一个beta版用于排除编译器生成的方法,你可以先用这个beta版本,后续解决第一个问题后将发布正式版本。

helloworld666 commented 6 months ago

非常感谢您的快速答复🙏。期待肉夹馍新版本的发布。

inversionhourglass commented 6 months ago

不客气,2.3.1-priview-1713791514已发布,可以暂时解决编译报错的问题

inversionhourglass commented 6 months ago

已发布2.3.1正式版