JTe*_*ech 2 c# partial-classes event-handling
我需要为一个由模板生成的类注册一个事件处理程序 - 在EntityFramework中的T4模板.
目前,我们编辑了生成的代码,以在生成的类(模型上下文)的构造函数中注册处理程序.
当前代码:
public MyAppContext(string connectionString)
: base(connectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
// Register the event handler
this.Connection.StateChange += Connection_StateChange;
}
Run Code Online (Sandbox Code Playgroud)
问题是,如果将来重新生成代码,那么上面的代码将被破坏,事件处理程序将不再被连接......
代码重新生成从最小的事情自动发生,例如打开EF Designer并在画布上移动表格!因此,我们不要依赖于将自定义代码留在生成的类中.
无论如何我们可以将注册放在一个部分类中,并保持生成的代码不变?
EG是否存在某种事件,一旦调用构造函数,它将始终被触发?
这个问题的答案是编辑T4模板以在构造函数的末尾放入方法调用.
在由模板生成的部分类的上下文中,此方法需要是部分方法.
模板需要包含partial方法的定义.
然后你的自定义部分类可以实现该方法,它将由生成的部分类中定义的构造函数调用 - 现在您可以根据需要多次重新生成该部分类,并保证将始终调用部分方法 - 假设没有人编辑模板.
如果有人编辑模板并删除了部分方法的定义,那么您将收到编译器错误 - 易于修复.
如果有人编辑模板并从构造函数中删除对partial方法的调用,那么很遗憾,编译器无法帮助您 - 需要注意的事项!
这是我在tid-bits中的解决方案:
T4模板代码'MyApp.Context.tt'中的构造函数和部分方法定义的片段(有关T4语法及其在EntityFramework中的使用的详细解释,请参见此处):
public <#=code.Escape(container)#>(string connectionString)
: base(connectionString, ContainerName)
{
<#
WriteLazyLoadingEnabled(container);
#>
// Call the OnContextCreated() method to perform any necessary 'post creation' setup
OnContextCreated();
}
// Define the OnContextCreated partial method so that the accompanying partial Context
// class can implement this method.
partial void OnContextCreated();
Run Code Online (Sandbox Code Playgroud)
实现partial方法并连接事件处理程序的自定义partial类:
public partial class MyAppContext
{
/// <summary>
/// Performs all 'post creation' operations for the MyAppContext
///
/// *********************************
/// NOTE: If you get a compiler error:
/// 'No defining declaration found for implementing declaration of partial method 'OnContextCreated()'
/// then it is likely that the partial class MyApp.Context.cs does not contain a corresponding
/// definition for the partial method OnContextCreated().
/// This can occur if the MyApp.Context.tt template no longer generates the definition.
/// SOLUTION: Edit the MyApp.Context.tt T4 template to ensure that that partial method is defined AND
/// that it is called from EACH MyAppContext() constructor.
/// *********************************
///
/// </summary>
partial void OnContextCreated()
{
// Register the event handler
this.Connection.StateChange += Connection_StateChange;
}
}
Run Code Online (Sandbox Code Playgroud)