Próbuję dostosować generowanie kodu programu Windows Forms Designer do wersji InitializeComponent
. Artykuł MSDN "Customizing Code Generation in the .NET Framework Visual Designers" zawiera sekcję "Controlling Code Generation", która wyjaśnia podstawy, w jaki sposób można to zrobić.Jak mogę dostosować generowanie kodu InitializeComponent? Dokładniej, jak mogę postprocesować cały wygenerowany kod?
mam ściśle przestrzegać przykład w powyższym artykule:
//using System.ComponentModel.Design.Serialization;
class SomeFormSerializer : CodeDomSerializer
{
public override object Serialize(IDesignerSerializationManager manager,
object value)
{
// first, let the default serializer do its work:
var baseSerializer = (CodeDomSerializer)manager.GetSerializer(
typeof(Form).BaseType, typeof(CodeDomSerializer));
object codeObject = baseSerializer.Serialize(manager, value);
// then, modify the generated CodeDOM -- add a comment as the 1st line:
if (codeObject is CodeStatementCollection)
{
var statements = (CodeStatementCollection)codeObject;
statements.Insert(0, new CodeCommentStatement("CODEDOM WAS HERE"));
}
// finally, return the modified CodeDOM:
return codeObject;
}
}
Teraz hak to do mojego formularza SomeForm
:
[DesignerSerializer(typeof(SomeFormSerializer), typeof(CodeDomSerializer))]
class SomeForm : Form { … }
Projektant formularzy może następnie wygenerować następujący kod InitializeComponent
:
private void InitializeComponent()
{
… /* (general setup code, such as a call to `this.SuspendLayout`) */
//
// someButton
//
… /* (someButton's properties are set) */
// CODEDOM WAS HERE!
//
// SomeForm
//
… /* (form's properties are set) */
… /* (general setup code, such as a call to `this.ResumeLayout`) */
}
Pamiętaj, że comme nt // CODEDOM WAS HERE
nie został dodany jako pierwsza linia w InitializeComponent
, ale tylko jako pierwsza linia bloku kodu, który zajmuje się właściwościami samego obiektu formularza.
Co powinienem zrobić, gdybym chciał móc zmodyfikować wygenerowany CodeDOM całej metody, a nie tylko części, która zajmuje się konkretnym obiektem?
Tło: Dlaczego chcę to zrobić? W Windows Forms, jeśli chce się elastycznej konwersji wartości podczas wiązania danych, zwykle trzeba uciec się do subskrypcji zdarzeń
Format
iParse
jakiegoś szczególnego obiektuBinding
. Dlatego tworzę wyspecjalizowaną podklasęBinding
(nazwijmy ją:ConvertingBinding
), która nieco upraszcza ten proces.Problem polega na tym, że po skonfigurowaniu powiązań danych w Projektancie formularzy systemu Windows wygenerowany kod tworzy instancje
Binding
; jednak chciałbym, aby projektant zamiast tego utworzył moją wyspecjalizowaną podklasę. Moje obecne podejście polega na umożliwieniu projektantowi najpierw utworzenia drzewa CodeDOM, a następnie chodzenia po tym drzewie i zastępowania wszystkich wystąpieńBinding
przez instancje zConvertingBinding
.
To niemal co chcę. Wydaje się, że wystarczy zastąpić instancje 'Binding'; ale nadal nie mogę uzyskać dostępu do całej metody, tj. pierwszych kilku wierszy i ostatnich kilku wierszy w 'InitializeComponent'. – stakx
@stakx: Pierwsze kilka wierszy w 'InitializeComponent' składa się zawsze z obiektów' CodeVariableDeclarationStatement'. Jeśli wprowadzisz zmiany do któregokolwiek z tych obiektów w 'CodeStatementCollection' lub dodasz nowe" CodeVariableDeclarationStatement "do kolekcji, wszystkie te zmiany pojawią się w pierwszych kilku wierszach. Każda inna linia 'CodeStatement' pojawi się po wszystkich liniach' CodeVariableDeclarationStatement'. – nempoBu4