How to auto generate interface implementations

G

Guest

I've created an "Add Item" wizard for VB.NET 2003 that allows a user to add a
specialized class that works with my application framework. In the wizard,
the user can select the interfaces they would like to support. During the
code generation phase, I add an "Implements Ixxx" for each interface they
select, but I've not yet figured out how to add the skeleton implementation
for those interfaces. Once the user opens the class in the VS IDE, they
can position the cursor after the interface name and hit return to
auto-generate the implementation. Is there a way to programmatically cause
VB.NET to generate the skeleton implementation for these interfaces using the
extensibility model?

Thanks!
Bill
 
P

Peter Huang [MSFT]

Hi

Based on my knowledge, this job done by VS.NET IDE is achieved by
Intellisense which is not exposed by DTE(IDE) Object Modal.
So far I think we have to do that ourselves.
Here is a similar issue about get...set generator.
http://www.codeproject.com/macro/PropertyGenerator.asp

If you have question about the DTE object modal, you may try to post in the
specifed VS.NET IDE extensive newsgroup.
microsoft.public.vstudio.extensibility

If you still have any concern please feel free to post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jay B. Harlow [MVP - Outlook]

Bill,
In addition to Peter's comments.

What are you using to generate the class itself?

Have you considered using Reflection to read the definition of the
Interface, then adding those members to the code that you are creating?

I will try to post an example of using Reflection to read the definition of
an Interface to generate code later...

Hope this helps
Jay

| I've created an "Add Item" wizard for VB.NET 2003 that allows a user to
add a
| specialized class that works with my application framework. In the
wizard,
| the user can select the interfaces they would like to support. During the
| code generation phase, I add an "Implements Ixxx" for each interface they
| select, but I've not yet figured out how to add the skeleton
implementation
| for those interfaces. Once the user opens the class in the VS IDE, they
| can position the cursor after the interface name and hit return to
| auto-generate the implementation. Is there a way to programmatically
cause
| VB.NET to generate the skeleton implementation for these interfaces using
the
| extensibility model?
|
| Thanks!
| Bill
|
|
 
G

Guest

Hi Peter,

Thanks for your suggestions. I'll take a look at the PropertyGenerator
example you cited.

Best regards,
Bill
 
G

Guest

Hi Jay,

Thank you for your reply. I figured reflection could be used to
accomplished this task, but I was trying to avoid coding it if the capability
was already available in the DTE. Since it is not, I would sure appreciate
any sample code you can provide.

Best regards,
Bill
 
J

Jay B. Harlow [MVP - Outlook]

Bill,
Here is an example that uses Reflection & the Code Dom to implement an
interface.

There seems to be a problem with the CodeMemberEvent.ImplementationTypes
member of the CodeDom. For example if I

Implements System.ComponentModel.IComponent


My routine creates:

Public Event Disposed As System.EventHandler

Instead of:

Public Event Disposed As System.EventHandler Implements
IComponent.Disposed

The code for Properties & Methods work, however Events fail, so I'm not sure
what the problem is. I'm checking into it. Cannot think of a workaround
right now.

You can use CodeTypeMember.Attributes to control the visibility of the
generated members. Or use PrivateImplementationType member of
CodeMemberEvent, CodeMemberProperty & CodeMemberMethod to "hide" the
implementation of the methods...

Hope this helps
Jay

---x--- cut here ---x---
Option Strict On
Option Explicit On

Imports System.CodeDom
Imports System.CodeDom.Compiler

Imports System.IO
Imports System.Reflection

Public Module GenerateInterface

Public Sub Main()
Dim unit As New CodeCompileUnit

Dim ns As New CodeNamespace("Sample")
unit.Namespaces.Add(ns)

Dim type As CodeTypeDeclaration = BuildClass(ns, "BillRust",
GetType(Object))

ImplementInterface(type,
GetType(System.ComponentModel.IBindingList))

GenerateCode(unit, "BillRust.vb", New VBCodeProvider)
End Sub

Private Sub ImplementInterface(ByVal baseType As CodeTypeDeclaration,
ByVal implementedType As Type)
baseType.BaseTypes.Add(New CodeTypeReference(implementedType))

ImplementInterfaceMembers(baseType, implementedType)

For Each baseInterface As Type In implementedType.GetInterfaces()
ImplementInterfaceMembers(baseType, baseInterface)
Next

End Sub

Private Sub ImplementInterfaceMembers(ByVal baseType As
CodeTypeDeclaration, ByVal implementedType As Type)
ImplementInterfaceEvents(baseType, implementedType)
ImplementInterfaceProperties(baseType, implementedType)
ImplementInterfaceMethods(baseType, implementedType)
End Sub

Private Sub ImplementInterfaceEvents(ByVal baseType As
CodeTypeDeclaration, ByVal implementedType As Type)
For Each [event] As EventInfo In implementedType.GetEvents()
Dim member As New CodeMemberEvent
member.Name = [event].Name
member.Attributes = MemberAttributes.Public
member.Type = New CodeTypeReference([event].EventHandlerType)
member.ImplementationTypes.Add(implementedType)
baseType.Members.Add(member)
Next
End Sub

Private Sub ImplementInterfaceProperties(ByVal baseType As
CodeTypeDeclaration, ByVal implementedType As Type)
For Each [property] As PropertyInfo In
implementedType.GetProperties()
Dim member As New CodeMemberProperty
member.Name = [property].Name
member.Attributes = MemberAttributes.Public
member.HasGet = [property].CanRead
member.HasSet = [property].CanWrite
member.Type = New CodeTypeReference([property].PropertyType)
ImplementParameters(member.Parameters,
[property].GetIndexParameters())
member.ImplementationTypes.Add(implementedType)
baseType.Members.Add(member)
Next
End Sub

Private Sub ImplementInterfaceMethods(ByVal baseType As
CodeTypeDeclaration, ByVal implementedType As Type)
Static void As Type = Type.GetType("System.Void")
For Each [method] As MethodInfo In implementedType.GetMethods()
If Not [method].IsSpecialName Then
Dim member As New CodeMemberMethod
member.Attributes = MemberAttributes.Public
member.Name = [method].Name
member.ReturnType = New
CodeTypeReference([method].ReturnType)
ImplementParameters(member.Parameters,
[method].GetParameters())
member.ImplementationTypes.Add(implementedType)
baseType.Members.Add(member)
End If
Next
End Sub

Private Sub ImplementParameters(ByVal outputParameters As
CodeParameterDeclarationExpressionCollection, ByVal inputParameters() As
ParameterInfo)
For Each parameter As ParameterInfo In inputParameters
Dim value As New CodeParameterDeclarationExpression
value.Name = parameter.Name
value.Type = New CodeTypeReference(parameter.ParameterType)
outputParameters.Add(value)
Next
End Sub

Private Function BuildClass(ByVal ns As CodeNamespace, ByVal name As
String, ByVal baseType As Type) As CodeTypeDeclaration
Dim type As New CodeTypeDeclaration(name)
ns.Types.Add(type)

type.BaseTypes.Add(baseType)

Return type
End Function

Private Sub GenerateCode(ByVal unit As CodeCompileUnit, ByVal file As
String, ByVal provider As CodeDomProvider)
Dim output As New StreamWriter(file)
Dim generator As ICodeGenerator = provider.CreateGenerator()
Dim options As New CodeGeneratorOptions
options.BlankLinesBetweenMembers = True
options.BracingStyle = "C"

unit.UserData.Add("AllowLateBound", False)
unit.UserData.Add("RequireVariableDeclaration", True)

Try
generator.GenerateCodeFromCompileUnit(unit, output, options)
Catch e As Exception
Debug.WriteLine(e, "GenerateCode")
Finally
output.Flush()
output.Close()
provider.Dispose()
End Try
End Sub

End Module

---x--- cut here ---x---

| Hi Jay,
|
| Thank you for your reply. I figured reflection could be used to
| accomplished this task, but I was trying to avoid coding it if the
capability
| was already available in the DTE. Since it is not, I would sure
appreciate
| any sample code you can provide.
|
| Best regards,
| Bill
|
| "Jay B. Harlow [MVP - Outlook]" wrote:
|
| > Bill,
| > In addition to Peter's comments.
| >
| > What are you using to generate the class itself?
| >
| > Have you considered using Reflection to read the definition of the
| > Interface, then adding those members to the code that you are creating?
| >
| > I will try to post an example of using Reflection to read the definition
of
| > an Interface to generate code later...
| >
| > Hope this helps
| > Jay
| >
| > | > | I've created an "Add Item" wizard for VB.NET 2003 that allows a user
to
| > add a
| > | specialized class that works with my application framework. In the
| > wizard,
| > | the user can select the interfaces they would like to support. During
the
| > | code generation phase, I add an "Implements Ixxx" for each interface
they
| > | select, but I've not yet figured out how to add the skeleton
| > implementation
| > | for those interfaces. Once the user opens the class in the VS IDE,
they
| > | can position the cursor after the interface name and hit return to
| > | auto-generate the implementation. Is there a way to programmatically
| > cause
| > | VB.NET to generate the skeleton implementation for these interfaces
using
| > the
| > | extensibility model?
| > |
| > | Thanks!
| > | Bill
| > |
| > |
| >
| >
| >
 
G

Guest

Thanks, Jay. I'll give it a try :)

Jay B. Harlow said:
Bill,
Here is an example that uses Reflection & the Code Dom to implement an
interface.

There seems to be a problem with the CodeMemberEvent.ImplementationTypes
member of the CodeDom. For example if I

Implements System.ComponentModel.IComponent


My routine creates:

Public Event Disposed As System.EventHandler

Instead of:

Public Event Disposed As System.EventHandler Implements
IComponent.Disposed

The code for Properties & Methods work, however Events fail, so I'm not sure
what the problem is. I'm checking into it. Cannot think of a workaround
right now.

You can use CodeTypeMember.Attributes to control the visibility of the
generated members. Or use PrivateImplementationType member of
CodeMemberEvent, CodeMemberProperty & CodeMemberMethod to "hide" the
implementation of the methods...

Hope this helps
Jay

---x--- cut here ---x---
Option Strict On
Option Explicit On

Imports System.CodeDom
Imports System.CodeDom.Compiler

Imports System.IO
Imports System.Reflection

Public Module GenerateInterface

Public Sub Main()
Dim unit As New CodeCompileUnit

Dim ns As New CodeNamespace("Sample")
unit.Namespaces.Add(ns)

Dim type As CodeTypeDeclaration = BuildClass(ns, "BillRust",
GetType(Object))

ImplementInterface(type,
GetType(System.ComponentModel.IBindingList))

GenerateCode(unit, "BillRust.vb", New VBCodeProvider)
End Sub

Private Sub ImplementInterface(ByVal baseType As CodeTypeDeclaration,
ByVal implementedType As Type)
baseType.BaseTypes.Add(New CodeTypeReference(implementedType))

ImplementInterfaceMembers(baseType, implementedType)

For Each baseInterface As Type In implementedType.GetInterfaces()
ImplementInterfaceMembers(baseType, baseInterface)
Next

End Sub

Private Sub ImplementInterfaceMembers(ByVal baseType As
CodeTypeDeclaration, ByVal implementedType As Type)
ImplementInterfaceEvents(baseType, implementedType)
ImplementInterfaceProperties(baseType, implementedType)
ImplementInterfaceMethods(baseType, implementedType)
End Sub

Private Sub ImplementInterfaceEvents(ByVal baseType As
CodeTypeDeclaration, ByVal implementedType As Type)
For Each [event] As EventInfo In implementedType.GetEvents()
Dim member As New CodeMemberEvent
member.Name = [event].Name
member.Attributes = MemberAttributes.Public
member.Type = New CodeTypeReference([event].EventHandlerType)
member.ImplementationTypes.Add(implementedType)
baseType.Members.Add(member)
Next
End Sub

Private Sub ImplementInterfaceProperties(ByVal baseType As
CodeTypeDeclaration, ByVal implementedType As Type)
For Each [property] As PropertyInfo In
implementedType.GetProperties()
Dim member As New CodeMemberProperty
member.Name = [property].Name
member.Attributes = MemberAttributes.Public
member.HasGet = [property].CanRead
member.HasSet = [property].CanWrite
member.Type = New CodeTypeReference([property].PropertyType)
ImplementParameters(member.Parameters,
[property].GetIndexParameters())
member.ImplementationTypes.Add(implementedType)
baseType.Members.Add(member)
Next
End Sub

Private Sub ImplementInterfaceMethods(ByVal baseType As
CodeTypeDeclaration, ByVal implementedType As Type)
Static void As Type = Type.GetType("System.Void")
For Each [method] As MethodInfo In implementedType.GetMethods()
If Not [method].IsSpecialName Then
Dim member As New CodeMemberMethod
member.Attributes = MemberAttributes.Public
member.Name = [method].Name
member.ReturnType = New
CodeTypeReference([method].ReturnType)
ImplementParameters(member.Parameters,
[method].GetParameters())
member.ImplementationTypes.Add(implementedType)
baseType.Members.Add(member)
End If
Next
End Sub

Private Sub ImplementParameters(ByVal outputParameters As
CodeParameterDeclarationExpressionCollection, ByVal inputParameters() As
ParameterInfo)
For Each parameter As ParameterInfo In inputParameters
Dim value As New CodeParameterDeclarationExpression
value.Name = parameter.Name
value.Type = New CodeTypeReference(parameter.ParameterType)
outputParameters.Add(value)
Next
End Sub

Private Function BuildClass(ByVal ns As CodeNamespace, ByVal name As
String, ByVal baseType As Type) As CodeTypeDeclaration
Dim type As New CodeTypeDeclaration(name)
ns.Types.Add(type)

type.BaseTypes.Add(baseType)

Return type
End Function

Private Sub GenerateCode(ByVal unit As CodeCompileUnit, ByVal file As
String, ByVal provider As CodeDomProvider)
Dim output As New StreamWriter(file)
Dim generator As ICodeGenerator = provider.CreateGenerator()
Dim options As New CodeGeneratorOptions
options.BlankLinesBetweenMembers = True
options.BracingStyle = "C"

unit.UserData.Add("AllowLateBound", False)
unit.UserData.Add("RequireVariableDeclaration", True)

Try
generator.GenerateCodeFromCompileUnit(unit, output, options)
Catch e As Exception
Debug.WriteLine(e, "GenerateCode")
Finally
output.Flush()
output.Close()
provider.Dispose()
End Try
End Sub

End Module

---x--- cut here ---x---

| Hi Jay,
|
| Thank you for your reply. I figured reflection could be used to
| accomplished this task, but I was trying to avoid coding it if the
capability
| was already available in the DTE. Since it is not, I would sure
appreciate
| any sample code you can provide.
|
| Best regards,
| Bill
|
| "Jay B. Harlow [MVP - Outlook]" wrote:
|
| > Bill,
| > In addition to Peter's comments.
| >
| > What are you using to generate the class itself?
| >
| > Have you considered using Reflection to read the definition of the
| > Interface, then adding those members to the code that you are creating?
| >
| > I will try to post an example of using Reflection to read the definition
of
| > an Interface to generate code later...
| >
| > Hope this helps
| > Jay
| >
| > | > | I've created an "Add Item" wizard for VB.NET 2003 that allows a user
to
| > add a
| > | specialized class that works with my application framework. In the
| > wizard,
| > | the user can select the interfaces they would like to support. During
the
| > | code generation phase, I add an "Implements Ixxx" for each interface
they
| > | select, but I've not yet figured out how to add the skeleton
| > implementation
| > | for those interfaces. Once the user opens the class in the VS IDE,
they
| > | can position the cursor after the interface name and hit return to
| > | auto-generate the implementation. Is there a way to programmatically
| > cause
| > | VB.NET to generate the skeleton implementation for these interfaces
using
| > the
| > | extensibility model?
| > |
| > | Thanks!
| > | Bill
| > |
| > |
| >
| >
| >
 
J

Jay B. Harlow [MVP - Outlook]

Bill,
| > The code for Properties & Methods work, however Events fail, so I'm not
sure
| > what the problem is. I'm checking into it. Cannot think of a workaround
| > right now.
Just realized: If events are important, using a CodeSnippet may be the
workaround, I don't have an example right now.

I'm going to try my routine in VS.NET 2005 to see if it has the same problem
with events.

Hope this helps
Jay

| Thanks, Jay. I'll give it a try :)
|
| "Jay B. Harlow [MVP - Outlook]" wrote:
|
| > Bill,
| > Here is an example that uses Reflection & the Code Dom to implement an
| > interface.
| >
| > There seems to be a problem with the CodeMemberEvent.ImplementationTypes
| > member of the CodeDom. For example if I
| >
| > Implements System.ComponentModel.IComponent
| >
| >
| > My routine creates:
| >
| > Public Event Disposed As System.EventHandler
| >
| > Instead of:
| >
| > Public Event Disposed As System.EventHandler Implements
| > IComponent.Disposed
| >
| > The code for Properties & Methods work, however Events fail, so I'm not
sure
| > what the problem is. I'm checking into it. Cannot think of a workaround
| > right now.
| >
| > You can use CodeTypeMember.Attributes to control the visibility of the
| > generated members. Or use PrivateImplementationType member of
| > CodeMemberEvent, CodeMemberProperty & CodeMemberMethod to "hide" the
| > implementation of the methods...
| >
| > Hope this helps
| > Jay
| >
| > ---x--- cut here ---x---
| > Option Strict On
| > Option Explicit On
| >
| > Imports System.CodeDom
| > Imports System.CodeDom.Compiler
| >
| > Imports System.IO
| > Imports System.Reflection
| >
| > Public Module GenerateInterface
| >
| > Public Sub Main()
| > Dim unit As New CodeCompileUnit
| >
| > Dim ns As New CodeNamespace("Sample")
| > unit.Namespaces.Add(ns)
| >
| > Dim type As CodeTypeDeclaration = BuildClass(ns, "BillRust",
| > GetType(Object))
| >
| > ImplementInterface(type,
| > GetType(System.ComponentModel.IBindingList))
| >
| > GenerateCode(unit, "BillRust.vb", New VBCodeProvider)
| > End Sub
| >
| > Private Sub ImplementInterface(ByVal baseType As
CodeTypeDeclaration,
| > ByVal implementedType As Type)
| > baseType.BaseTypes.Add(New CodeTypeReference(implementedType))
| >
| > ImplementInterfaceMembers(baseType, implementedType)
| >
| > For Each baseInterface As Type In
implementedType.GetInterfaces()
| > ImplementInterfaceMembers(baseType, baseInterface)
| > Next
| >
| > End Sub
| >
| > Private Sub ImplementInterfaceMembers(ByVal baseType As
| > CodeTypeDeclaration, ByVal implementedType As Type)
| > ImplementInterfaceEvents(baseType, implementedType)
| > ImplementInterfaceProperties(baseType, implementedType)
| > ImplementInterfaceMethods(baseType, implementedType)
| > End Sub
| >
| > Private Sub ImplementInterfaceEvents(ByVal baseType As
| > CodeTypeDeclaration, ByVal implementedType As Type)
| > For Each [event] As EventInfo In implementedType.GetEvents()
| > Dim member As New CodeMemberEvent
| > member.Name = [event].Name
| > member.Attributes = MemberAttributes.Public
| > member.Type = New
CodeTypeReference([event].EventHandlerType)
| > member.ImplementationTypes.Add(implementedType)
| > baseType.Members.Add(member)
| > Next
| > End Sub
| >
| > Private Sub ImplementInterfaceProperties(ByVal baseType As
| > CodeTypeDeclaration, ByVal implementedType As Type)
| > For Each [property] As PropertyInfo In
| > implementedType.GetProperties()
| > Dim member As New CodeMemberProperty
| > member.Name = [property].Name
| > member.Attributes = MemberAttributes.Public
| > member.HasGet = [property].CanRead
| > member.HasSet = [property].CanWrite
| > member.Type = New CodeTypeReference([property].PropertyType)
| > ImplementParameters(member.Parameters,
| > [property].GetIndexParameters())
| > member.ImplementationTypes.Add(implementedType)
| > baseType.Members.Add(member)
| > Next
| > End Sub
| >
| > Private Sub ImplementInterfaceMethods(ByVal baseType As
| > CodeTypeDeclaration, ByVal implementedType As Type)
| > Static void As Type = Type.GetType("System.Void")
| > For Each [method] As MethodInfo In implementedType.GetMethods()
| > If Not [method].IsSpecialName Then
| > Dim member As New CodeMemberMethod
| > member.Attributes = MemberAttributes.Public
| > member.Name = [method].Name
| > member.ReturnType = New
| > CodeTypeReference([method].ReturnType)
| > ImplementParameters(member.Parameters,
| > [method].GetParameters())
| > member.ImplementationTypes.Add(implementedType)
| > baseType.Members.Add(member)
| > End If
| > Next
| > End Sub
| >
| > Private Sub ImplementParameters(ByVal outputParameters As
| > CodeParameterDeclarationExpressionCollection, ByVal inputParameters() As
| > ParameterInfo)
| > For Each parameter As ParameterInfo In inputParameters
| > Dim value As New CodeParameterDeclarationExpression
| > value.Name = parameter.Name
| > value.Type = New CodeTypeReference(parameter.ParameterType)
| > outputParameters.Add(value)
| > Next
| > End Sub
| >
| > Private Function BuildClass(ByVal ns As CodeNamespace, ByVal name As
| > String, ByVal baseType As Type) As CodeTypeDeclaration
| > Dim type As New CodeTypeDeclaration(name)
| > ns.Types.Add(type)
| >
| > type.BaseTypes.Add(baseType)
| >
| > Return type
| > End Function
| >
| > Private Sub GenerateCode(ByVal unit As CodeCompileUnit, ByVal file
As
| > String, ByVal provider As CodeDomProvider)
| > Dim output As New StreamWriter(file)
| > Dim generator As ICodeGenerator = provider.CreateGenerator()
| > Dim options As New CodeGeneratorOptions
| > options.BlankLinesBetweenMembers = True
| > options.BracingStyle = "C"
| >
| > unit.UserData.Add("AllowLateBound", False)
| > unit.UserData.Add("RequireVariableDeclaration", True)
| >
| > Try
| > generator.GenerateCodeFromCompileUnit(unit, output, options)
| > Catch e As Exception
| > Debug.WriteLine(e, "GenerateCode")
| > Finally
| > output.Flush()
| > output.Close()
| > provider.Dispose()
| > End Try
| > End Sub
| >
| > End Module
| >
| > ---x--- cut here ---x---
| >
| > | > | Hi Jay,
| > |
| > | Thank you for your reply. I figured reflection could be used to
| > | accomplished this task, but I was trying to avoid coding it if the
| > capability
| > | was already available in the DTE. Since it is not, I would sure
| > appreciate
| > | any sample code you can provide.
| > |
| > | Best regards,
| > | Bill
| > |
| > | "Jay B. Harlow [MVP - Outlook]" wrote:
| > |
| > | > Bill,
| > | > In addition to Peter's comments.
| > | >
| > | > What are you using to generate the class itself?
| > | >
| > | > Have you considered using Reflection to read the definition of the
| > | > Interface, then adding those members to the code that you are
creating?
| > | >
| > | > I will try to post an example of using Reflection to read the
definition
| > of
| > | > an Interface to generate code later...
| > | >
| > | > Hope this helps
| > | > Jay
| > | >
| > | > | > | > | I've created an "Add Item" wizard for VB.NET 2003 that allows a
user
| > to
| > | > add a
| > | > | specialized class that works with my application framework. In
the
| > | > wizard,
| > | > | the user can select the interfaces they would like to support.
During
| > the
| > | > | code generation phase, I add an "Implements Ixxx" for each
interface
| > they
| > | > | select, but I've not yet figured out how to add the skeleton
| > | > implementation
| > | > | for those interfaces. Once the user opens the class in the VS
IDE,
| > they
| > | > | can position the cursor after the interface name and hit return to
| > | > | auto-generate the implementation. Is there a way to
programmatically
| > | > cause
| > | > | VB.NET to generate the skeleton implementation for these
interfaces
| > using
| > | > the
| > | > | extensibility model?
| > | > |
| > | > | Thanks!
| > | > | Bill
| > | > |
| > | > |
| > | >
| > | >
| > | >
| >
| >
| >
 
P

Peter Huang [MSFT]

Hi Bill,

Thanks for your quickly reply!

If you still have any concern, please feel free to post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top