2012-04-19 43 views
3

我已經創建了一個組件來爲我們的項目進行本地化。我遇到的問題是我輸出的代碼被注入到InitializeComponent中發生得太晚了。CodeDomSerializer輸出訂購

this.components = new System.ComponentModel.Container(); 
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ucHome)); 
this.localizationResourceManager1 = new Compass0.Localization.LocalizationResourceManager(this.components); 
//Other designer code to create controls (this is all in the first block of code in InitializeComponent 
Compass0.Localization.XMLResourceManager.Create(typeof(ucViewHome), ref resources); //created by my code serializier 
// 
// btnLogin 
// 

等等等等

但什麼是由設計者情況是

this.components = new System.ComponentModel.Container(); 
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ucHome)); 
this.btnLogin = new ComponentFactory.Krypton.Toolkit.KryptonButton(); 
this.localizationResourceManager1 = new Compass0.Localization.LocalizationResourceManager(this.components); 
//Other designer code to create controls (this is all in the first block of code in InitializeComponent 
// 
// btnLogin 
// 
this. btnLogin.Name = "btnLogin"; 
this. btnLogin.Text = resources.GetString("btnLogin.Text"); 
Compass0.Localization.XMLResourceManager.Create(typeof(ucViewHome), ref resources); //created by my code serializier 

基本上,我需要迫使設計師把我的代碼後的3號線資源已經初始化。有沒有辦法以直接的方式做到這一點?我的代碼生成類如下。

public override object Deserialize(IDesignerSerializationManager manager, object codeDomObject) 
    { 
     CodeDomSerializer baseSerializer = (CodeDomSerializer)manager.GetSerializer(typeof(LocalizationResourceManager).BaseType, typeof(CodeDomSerializer)); 

     return baseSerializer.Deserialize(manager, codeDomObject); 
    } 

    public override object Serialize(IDesignerSerializationManager manager, object value) 
    { 
     CodeDomSerializer baseSerializer = (CodeDomSerializer)manager.GetSerializer(typeof(LocalizationResourceManager). 
      BaseType, typeof(CodeDomSerializer)); 

     object codeObject = baseSerializer.Serialize(manager, value); 

     if (codeObject is CodeStatementCollection) 
     { 
      CodeStatementCollection statements = (CodeStatementCollection)codeObject; 

      CodeTypeDeclaration classTypeDeclaration = (CodeTypeDeclaration)manager.GetService(typeof(CodeTypeDeclaration)); 

      CodeExpression typeofExpression = new CodeTypeOfExpression(classTypeDeclaration.Name); 

      CodeDirectionExpression resourceRef = new CodeDirectionExpression(FieldDirection.Ref, new CodeVariableReferenceExpression("resources")); 

      CodeExpression ResourceManagerAssignment = new CodeMethodInvokeExpression(
       new CodeTypeReferenceExpression(typeof(XMLResourceManager).ToString()), 
       "Create", new CodeExpression[] { typeofExpression, resourceRef }); 


      statements.Insert(0, new CodeExpressionStatement(ResourceManagerAssignment));    
     } 

     return codeObject; 
    } 

回答

3

我知道這是真的晚了,但任何人誰在這個問題絆倒......

我在做同樣的事情,解決問題我只是確保創建我的定位控制/序列化首先創建一個繼承自ComponentDesigner的類,該類使用獲取控件列表的Initialize方法,將其自身刪除並重新添加到列表頂部。然後我將Designer屬性添加到我的自定義組件。

這是在VB中,如果有人需要它轉換成C#讓我知道...

<Designer(GetType(LocalizerDesigner))> 
<DesignerSerializer(GetType(LocalizerSerializer), GetType(CodeDomSerializer))> 
Public Class Localizer 
    Inherits Component 

    Public Sub GetResourceManager(type As Type, ByRef manager As ComponentResourceManager) 
     ' Replace resource manager w/ new one. 
    End Sub 

End Class 

Public Class LocalizerSerializer 
    Inherits CodeDomSerializer 

    Public Overrides Function Deserialize(manager As IDesignerSerializationManager, codeObject As Object) As Object 
     Dim baseSerializer As CodeDomSerializer = DirectCast(manager.GetSerializer(GetType(Component), GetType(CodeDomSerializer)), CodeDomSerializer) 
     Return baseSerializer.Deserialize(manager, codeObject) 
    End Function 

    Public Overrides Function Serialize(manager As IDesignerSerializationManager, value As Object) As Object 
     Dim baseSerializer As CodeDomSerializer = DirectCast(manager.GetSerializer(GetType(Component), GetType(CodeDomSerializer)), CodeDomSerializer) 

     Dim codeObject As Object = baseSerializer.Serialize(manager, value) 

     Dim statementCollection As CodeStatementCollection = TryCast(codeObject, CodeStatementCollection) 

     If statementCollection IsNot Nothing Then 
      Dim formClassTypeDeclaration As CodeTypeDeclaration = DirectCast(manager.GetService(GetType(CodeTypeDeclaration)), CodeTypeDeclaration) 
      Dim typeofFormExpression As New CodeTypeOfExpression(formClassTypeDeclaration.Name) 

      Dim outResourcesExpression As New CodeDirectionExpression(FieldDirection.Out, New CodeVariableReferenceExpression("resources")) 
      Dim getResourceManagerExpression As New CodeMethodInvokeExpression(MyBase.SerializeToExpression(manager, value), "GetResourceManager", 
                    {typeofFormExpression, outResourcesExpression}) 

      statementCollection.Add(New CodeExpressionStatement(getResourceManagerExpression)) 
     End If 
     Return codeObject 
    End Function 
End Class 

Public Class LocalizerDesigner 
    Inherits ComponentDesigner 

    Public Overrides Sub Initialize(component As IComponent) 
     MyBase.Initialize(component) 
     Dim designerHost As IDesignerHost = TryCast(GetService(GetType(IDesignerHost)), IDesignerHost) 
     If designerHost Is Nothing Then 
      Return 
     End If 

     Dim innerListProperty As Reflection.PropertyInfo = designerHost.Container.Components.GetType().GetProperty("InnerList", System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.FlattenHierarchy) 
     Dim innerList As ArrayList = TryCast(innerListProperty.GetValue(designerHost.Container.Components, Nothing), ArrayList) 

     If innerList Is Nothing OrElse innerList.IndexOf(component) <= 1 Then 
      Return 
     End If 

     innerList.Remove(component) 
     innerList.Insert(0, component) 
    End Sub 
End Class