如何在.designer.cs文件中生成方法

时间:2014-01-29 17:08:57

标签: winforms serialization codedom

在自定义CodeDomSerializer中,您可以向该类添加自定义成员(例如事件处理程序方法)。

生成的成员总是以Form1.cs而不是Form1.designer.cs结束。 有没有办法在设计器文件的部分类中插入生成器方法?

(方法的内容将自动生成,不应触及。)

添加方法的示例:

public class MasterDetailControlSerializer : CodeDomSerializer
{
    public override object Serialize(IDesignerSerializationManager manager, object value)
    {
        var baseClassSerializer = manager.GetSerializer(typeof(MasterDetailControl).BaseType, typeof(CodeDomSerializer)) as CodeDomSerializer;
        var r = (CodeStatementCollection)baseClassSerializer.Serialize(manager, value);
        var masterDetailControl = (MasterDetailControl)value;

        var method = new CodeMemberMethod();
        method.Name = masterDetailControl.Name + "_InitializeDetailComponent";
        method.Parameters.AddRange(new[] { new CodeParameterDeclarationExpression(typeof(object), "sender"), new CodeParameterDeclarationExpression(typeof(InitializeDetailComponentEventArgs), "e") });
        method.Attributes = MemberAttributes.Private;

        var type = manager.GetService<CodeTypeDeclaration>();
        type.Members.Add(method);

        r.Add(new CodeAttachEventStatement(
            new CodeEventReferenceExpression(base.GetExpression(manager, masterDetailControl), "InitializeDetailComponent"),
            new CodeDelegateCreateExpression(
                new CodeTypeReference(typeof(EventHandler<InitializeDetailComponentEventArgs>)),
                new CodeThisReferenceExpression(),
                method.Name
            )));

        return r;
    }
}

1 个答案:

答案 0 :(得分:1)

经过一些研究,逐步介绍Visual Studio代码,这非常有效:

public class MasterDetailControlSerializer : CodeDomSerializer
{
    private static void AddToDesignerTypeDeclaration(IDesignerSerializationManager manager, CodeTypeMember member)
    {
        var type = manager.GetService<CodeTypeDeclaration>();

        var initializeComponentMethod = type.Members.Cast<CodeTypeMember>().First(m => m.Name == "InitializeComponent");
        var designerTypeDeclaration = ((CodeTypeDeclaration)initializeComponentMethod.UserData[typeof(CodeTypeDeclaration)]);
        member.UserData[typeof(CodeTypeDeclaration)] = designerTypeDeclaration;
        member.UserData[typeof(CodeDomProvider)] = initializeComponentMethod.UserData[typeof(CodeDomProvider)];

        for (var i = 0; i < type.Members.Count; i++)
            if (type.Members[i].Name == member.Name)
            {
                type.Members.RemoveAt(i);
                break;
            }

        for (var i = 0; i < designerTypeDeclaration.Members.Count; i++)
            if (designerTypeDeclaration.Members[i].Name == member.Name)
            {
                designerTypeDeclaration.Members.RemoveAt(i);
                break;
            }

        // Must add to the main type declaration or Visual Studio will remove the method later.
        // The order of these two statements matters!
        type.Members.Add(member);
        // Add to the type declaration that goes in the designer file
        designerTypeDeclaration.Members.Add(member);
    }

    public override object Serialize(IDesignerSerializationManager manager, object value)
    {
        var baseClassSerializer = (CodeDomSerializer)manager.GetSerializer(typeof(MasterDetailControl).BaseType, typeof(CodeDomSerializer));
        var r = (CodeStatementCollection)baseClassSerializer.Serialize(manager, value);
        var masterDetailControl = (MasterDetailControl)value;

        var detailInitializationMethod = new CodeMemberMethod();
        detailInitializationMethod.Name = masterDetailControl.Name + "_InitializeDetailComponent";
        detailInitializationMethod.Parameters.AddRange(new[] { new CodeParameterDeclarationExpression(typeof(object), "sender"), new CodeParameterDeclarationExpression(typeof(InitializeDetailComponentEventArgs), "e") });
        detailInitializationMethod.Attributes = MemberAttributes.Private;


        AddToDesignerTypeDeclaration(manager, detailInitializationMethod);

        r.Add(new CodeAttachEventStatement(
            new CodeEventReferenceExpression(base.GetExpression(manager, masterDetailControl), "InitializeDetailComponent"),
            new CodeDelegateCreateExpression(
                new CodeTypeReference(typeof(EventHandler<InitializeDetailComponentEventArgs>)),
                new CodeThisReferenceExpression(),
                detailInitializationMethod.Name
            )));

        return r;
    }
}