I have a project that allows the users to write plugins. I include a small IDE that allows writing code in C# and VB.NET and compiling it using the CodeDom compilers. Each plugin inherits a specific base class.
To make life easier for the user, I included basic templates for the various plugin types. Basically when the user creates a new plugin of type XY he starts from a basic implementation similar to what you get when you write
Public Class Foo
Inherits BaseFoo
and press enter in Visual Studio. The uncool thing is, that I just added some text files containing the premade code to the resources and display it from there. This works well enough until changes are made in the definitions of the base classes because the premade code needs to be adjusted accordingly.
In the framework there exist classes derived from CodeDomProvider
like Microsoft.VisualBasic.VBCodeGenerator
that seem to contain the necessary methods to create code based on type definitions. However the CodeDom
methods seem to be designed to create new types from scratch for example for scripting purposes and don't interact very well with Reflection
in the sense, that I can't feed MethodInfos
and the like directly to CodeDom.
I could probably hack something together where I manually build the type to be generated, like
Dim v As New Microsoft.VisualBasic.VBCodeProvider
Dim t As New CodeDom.CodeTypeDeclaration("Foo")
t.Attributes = CodeDom.MemberAttributes.Public
Dim r As New CodeDom.CodeTypeReference(GetType(Foo))
t.BaseTypes.Add(r)
t.IsClass = True
t.Name = "TestClass"
Dim base = GetType(Foo)
For Each method In base.GetMethods
If (method.Attributes And Reflection.MethodAttributes.Abstract) > 0 Then
Dim m As New CodeDom.CodeMemberMethod()
For Each p In method.GetParameters
Dim newp As New CodeDom.CodeParameterDeclarationExpression(p.ParameterType, p.Name)
newp.Direction = If(p.IsIn, CodeDom.FieldDirection.In, CodeDom.FieldDirection.Out)
m.Parameters.Add(newp)
Next
m.Name = method.Name
m.Attributes = CodeDom.MemberAttributes.Public Or CodeDom.MemberAttributes.Override
t.Members.Add(m)
End If
Next
Dim w As New IO.StringWriter
Dim opts As New CodeDom.Compiler.CodeGeneratorOptions
v.GenerateCodeFromType(t, w, opts)
For an example class
Public MustInherit Class Foo
Public Property Foo1 As Double
Public Function What() As Double
Return Double.NaN
End Function
Public MustOverride Sub Test(ByRef Was As Double)
Public MustOverride ReadOnly Property Something As Double
End Class
this creates the output
Public Class TestClass
Inherits TypeGenerator.Foo
Public Overrides Sub Test(ByRef Was As System.Double&)
End Sub
Public Overrides Sub get_Something()
End Sub
End Class
This goes into the right direction, but it seems very prone to bugs and very fiddly. (On a side note, why does it implement the parameter as System.Double&
which does not even compile. As a ByVal
parameter it works).
Is there an easier way to achieve what I need?
- Have a base class
- Create a code template from the definitions therein at runtime
Aucun commentaire:
Enregistrer un commentaire