?
?
$(ProjectDir)Libs\Afterthought\Afterthought.Amender.exe "$(TargetPath)" "$(TargetDir)EntityFramework.Patterns.dll"
我實際上分析代碼好久,也沒整明白它是怎么運行的,看一下官方文檔明白了,原來。。。
?
Next, add the following as a post build step to your project to call the Afterthought Amender executable:
$(SolutionDir)packages\Afterthought.1.0.8\tools\Afterthought.Amender.exe "$(TargetPath)"
Please note that the
\Afterthought.1.0.8\
portion of the path should reflect the version of Afterthought that you are using. You can also use theAmender
build task in your project, but this requires manually editing the project to add this task. Since NuGet currently does not support modifying the project file directly in this way, Afterthought does not automatically configure itself to run for referenced projects.If you instead chose to go the source route, simply configure your target project to call
Afterthought.Amender.exe
referencing the compiled output of the `Afterthought.Amender' project. Also, you can debug the amendment process by configuring the 'Afterthought.Amender' project to amend your target assembly and run this project in debug mode.
原來在事件后期執行這樣的一個操作。
根據我們一直的習慣,直接在代碼中解決問題的,但是這個工具是先編譯通過,然后通過一個EXE程序來修改程序集,以達到效果。
然后修改的程序集你再用ILSpay看,會發現,
原始代碼:
?
[Auditable]
public class AuditableEntity
{
public int Id { get; set; }
public string Color { get; set; }
}
?
Afterthought 以后,從ILSpay看到的代碼,這一刻一切都明了了。。
using EntityFramework.Patterns.Extensions;
using System;
namespace EntityFramework.Patterns.Tests
{
[Archivable]
public class ArchivableEntity : IArchivable
{
string <DeletedBy>k__BackingField;
DateTime? <Deleted>k__BackingField;
public int Id
{
get;
set;
}
public float Value
{
get;
set;
}
public string DeletedBy
{
get
{
return this.<DeletedBy>k__BackingField;
}
set
{
this.<DeletedBy>k__BackingField = value;
}
}
public DateTime? Deleted
{
get
{
return this.<Deleted>k__BackingField;
}
set
{
this.<Deleted>k__BackingField = value;
}
}
}
}
?
?
然后,再看
[AttributeUsage(AttributeTargets.Assembly)]
public class AmendAttribute : Attribute, IAmendmentAttribute
{
IEnumerable<ITypeAmendment> IAmendmentAttribute.GetAmendments(Type target)
{
if (target.GetCustomAttributes(typeof(AuditableAttribute), true).Length > 0)
{
ConstructorInfo constructorInfo = typeof (AuditableAmender<>).MakeGenericType(target).GetConstructor(Type.EmptyTypes);
if (constructorInfo != null)
yield return (ITypeAmendment) constructorInfo.Invoke(new object[0]);
}
if (target.GetCustomAttributes(typeof(ArchivableAttribute), true).Length > 0)
{
ConstructorInfo constructorInfo = typeof(ArchivableAmender<>).MakeGenericType(target).GetConstructor(Type.EmptyTypes);
if (constructorInfo != null)
yield return (ITypeAmendment)constructorInfo.Invoke(new object[0]);
}
}
}
?
再看,
[assembly: Amend]
?
這家伙,通過在編譯完成后,修改了程序,只要實現了IAmendmentAttribute , 那個exe 就知道了。隨后一個字,更改dll文件啊,。。。,它就改了。 所以 也就是上個文件中 [pure] 也就有用了, maybe .net framework 了。
所以debug的時候,跟不到斷點也是正常的了。因為你的程序已經對應的不是原來的代碼了。
用一句歌詞說: 我還是原來的我。 但程序集已經不是原來的程序集了。
當然,我說的斷點是
public class AmendAttribute : Attribute, IAmendmentAttribute
中的斷點。