Pergunta

Inside a custom CodeDomSerializer, you can add a custom member (such as an event handler method) to the class.

The generated member always ends up in Form1.cs instead of Form1.designer.cs. Is there a way to insert the generator method inside the partial class in the designer file instead?

(The contents of the method will be autogenerated and should not be touched.)

Example of adding a method:

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;
    }
}
Foi útil?

Solução

After a bit of research stepping through Visual Studio code, this is working quite nicely:

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;
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top