![]() | |
![]() |
| | Thread Tools | Search this Thread | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
I?m developing a project in VB.NET 2003 to analyze the financial markets using several algorithms. To do that I created a ?mustinherit? class to manage the behavior of the standard algorithm, and then a number of inherited classes for each single algorithm. Since the algorithms are potentially infinite, I will never be able to code them all in the project at design time. So, I would like now to create an editor to allow the users (using my software GUI) to dynamically create a new class (inherited from the generic class) for each algorithm they want to use. I do not have any idea on how I can do it. I read something about the dynamic definition of Assemblies, but I do not want to create a new Assembly, I would only add (and save) a new inherited class to my existing assembly. Any help (samples, ideas, links) will be greatly appreciated. |
#3
| |||
| |||
|
|
Piggy <Piggy (AT) discussions (DOT) microsoft.com> wrote: I?m developing a project in VB.NET 2003 to analyze the financial markets using several algorithms. To do that I created a ?mustinherit? class to manage the behavior of the standard algorithm, and then a number of inherited classes for each single algorithm. Since the algorithms are potentially infinite, I will never be able to code them all in the project at design time. So, I would like now to create an editor to allow the users (using my software GUI) to dynamically create a new class (inherited from the generic class) for each algorithm they want to use. I do not have any idea on how I can do it. I read something about the dynamic definition of Assemblies, but I do not want to create a new Assembly, I would only add (and save) a new inherited class to my existing assembly. Any help (samples, ideas, links) will be greatly appreciated. I'm not entirely sure which bit is causing you problems, but Activator.CreateInstance is the way to go for creating new instances of a type which is only known at runtime. You can find all the types in an assembly which inherit from a given base class by using Assembly.GetTypes and then checking IsAssignableFrom for each type, passing in the base class. (This is better than using the BaseType property, as that will only find classes that inherit directly from the base class.) -- Jon Skeet - <skeet (AT) pobox (DOT) com http://www.pobox.com/~skeet If replying to the group, please do not mail me too |
#4
| |||
| |||
|
|
thank you very much for your reply. My problem is not about creating an instance of a type I am already doing this, now I would like to create dinamically a new type that inherit directly from the base class. The new type has to override a function of the base type, and the code of the override is to be provided by the user at runtime. I also need to save the new class. |
#5
| |||
| |||
|
|
Piggy <Piggy (AT) discussions (DOT) microsoft.com> wrote: thank you very much for your reply. My problem is not about creating an instance of a type I am already doing this, now I would like to create dinamically a new type that inherit directly from the base class. The new type has to override a function of the base type, and the code of the override is to be provided by the user at runtime. I also need to save the new class. Ah, I see. In that case, you should look at the System.Reflection.Emit namespace and the System.CodeDom namespace. Both should have a fair amount of documentation and examples in MSDN. -- Jon Skeet - <skeet (AT) pobox (DOT) com http://www.pobox.com/~skeet If replying to the group, please do not mail me too |
#6
| |||
| |||
|
|
Thank you Jon. I am looking at the System.Reflection.Emit and System.CodeDom namespaces "Jon Skeet [C# MVP]" wrote: Piggy <Piggy (AT) discussions (DOT) microsoft.com> wrote: thank you very much for your reply. My problem is not about creating an instance of a type I am already doing this, now I would like to create dinamically a new type that inherit directly from the base class. The new type has to override a function of the base type, and the code of the override is to be provided by the user at runtime. I also need to save the new class. Ah, I see. In that case, you should look at the System.Reflection.Emit namespace and the System.CodeDom namespace. Both should have a fair amount of documentation and examples in MSDN. -- Jon Skeet - <skeet (AT) pobox (DOT) com http://www.pobox.com/~skeet If replying to the group, please do not mail me too |
#7
| |||
| |||
|
|
Hey Piggy, I'm in the middle of writing several articles on creating dynamic types at runtime so I can help you with any specific questions you have. First, yes, you'll have to use Reflection.Emit. the annoying thing about that is that you have to emit IL opcodes into your type TypeBuilder. You could build a string of C# or VB and then run it through the CSharpCodeProvider or VBCodeProvider object to compile it, but this would be a fairly big perf hit, not to mention that you'r app would have to load a new assembly into memory after each compile. With Reflection.Emit you can use the same assembly over and over, each time you need to add a new dynamic class. The general rules with dynamic types is to code against a public interface. This is because you wont have any API to code against at design time. You should probably wrap your type builder logic in a class factory design pattern. This is useful since you wont be able to "new" a dynamic type. Like I said before, if you have any specific questions let me know and I'd be more than happy to help. Dynamic types are pretty cool to use. "Piggy" wrote: Thank you Jon. I am looking at the System.Reflection.Emit and System.CodeDom namespaces "Jon Skeet [C# MVP]" wrote: Piggy <Piggy (AT) discussions (DOT) microsoft.com> wrote: thank you very much for your reply. My problem is not about creating an instance of a type I am already doing this, now I would like to create dinamically a new type that inherit directly from the base class. The new type has to override a function of the base type, and the code of the override is to be provided by the user at runtime. I also need to save the new class. Ah, I see. In that case, you should look at the System.Reflection.Emit namespace and the System.CodeDom namespace. Both should have a fair amount of documentation and examples in MSDN. -- Jon Skeet - <skeet (AT) pobox (DOT) com http://www.pobox.com/~skeet If replying to the group, please do not mail me too |
#8
| |||
| |||
|
|
Hi John, I decided for the VBCodeProvider because I need to provide an editor functionality to my project. Only the user (obviously at runtime) decides how to override the critical function of the base class from which the new type will inherit. To do this I used the CodeSnippetUnit type to get the input text and VBCodeProvider to: 1-Generate the code 2-Save the code 3-Compile a new dll with the newly created type After creating the dll, I can load it throught Assembly.LoadFromFile. Working with the type is now easy, since it inherits from the base class I created in the main assembly. As for the problem of loading an assembly for each new class I (hope) it will not be a problem, only one of the new classes will be loaded of each operation. The following is the code I wrote. what do you think about it? Public Sub SaveCode() Dim LiteralCode As String = "Imports Microsoft.VisualBasic" & vbCrLf & "Imports FinancialFormulas" & vbCrLf & CodeRTF.Text '<<-- In CodeRTF (RichTextBox) the user writes the main code for the new class Dim CSU As New CodeSnippetCompileUnit(LiteralCode) Dim CodeWriter As IO.TextWriter = IO.File.CreateText("d:\tests\Prova.vb") Dim GOpts As New CodeGeneratorOptions Dim VBCoder As New VBCodeProvider Dim CGen As ICodeGenerator = VBCoder.CreateGenerator() CSU.ReferencedAssemblies.Add("System") CSU.ReferencedAssemblies.Add("Microsoft.VisualBasi c") CSU.ReferencedAssemblies.Add("C:\VBProgies\NET\Opt ions\OptionFormulas\bin\FinancialFormulas.dll") GOpts.ElseOnClosing = True CGen.GenerateCodeFromCompileUnit(CSU, CodeWriter, New System.CodeDom.Compiler.CodeGeneratorOptions) CodeWriter.Close() 'CodeRTF.LoadFile("d:\tests\Prova.vb") End Sub Public Function AddClass() As Boolean Dim VBCoder As New VBCodeProvider Dim CComp As ICodeCompiler = VBCoder.CreateCompiler Dim CParams As New CompilerParameters Dim EEn As IEnumerator If IO.File.Exists("d:\tests\Prova.dll") Then IO.File.Delete("d:\tests\Prova.dll") CParams.GenerateExecutable = False CParams.OutputAssembly = "d:\tests\Prova.dll" CParams.ReferencedAssemblies.Add("C:\VBProgies\NET \Options\OptionFormulas\bin\FinancialFormulas.dll" ) Dim Res As CompilerResults = CComp.CompileAssemblyFromFile(CParams, "d:\tests\Prova.vb") With Res If .Errors.Count <> 0 Then CodeRTF.Text &= vbCrLf & vbCrLf & "ERRORS FOUND!" & vbCrLf EEn = .Errors.GetEnumerator EEn.Reset() While EEn.MoveNext With CType(EEn.Current, CompilerError) CodeRTF.Text &= .ErrorText & " (Row " & .Line & ")" & vbCrLf End With End While Return False End If End With Return True End Function Public Function LoadClass() Dim sperem As [Assembly] = [Assembly].LoadFile("d:\tests\Prova.dll") Dim DynStrat As Type = sperem.GetType("DynInd") Dim Params() As Type = {GetType(String), GetType(String), GetType(Double), GetType(Double), GetType(FinancialFormulas.EquityPortfolioStrategie s.SingleIndexStrategy.MembersNumberMethodEnum), GetType(Integer)} Dim Values() As Object = {"Albert", "SX5E", CDbl(1000000000), CDbl(15), CType(0, FinancialFormulas.EquityPortfolioStrategies.Single IndexStrategy.MembersNumberMethodEnum), CType(13, Integer)} Dim CInfo As ConstructorInfo = DynStrat.GetConstructor(Params) Dim Strat As Object Try Strat = CInfo.Invoke(Values) Catch ex As Exception End Try MsgBox(Strat.GetTargetPortfolio(Now.Date)) End Function Thank you very much "john conwell" wrote: Hey Piggy, I'm in the middle of writing several articles on creating dynamic types at runtime so I can help you with any specific questions you have. First, yes, you'll have to use Reflection.Emit. the annoying thing about that is that you have to emit IL opcodes into your type TypeBuilder. You could build a string of C# or VB and then run it through the CSharpCodeProvider or VBCodeProvider object to compile it, but this would be a fairly big perf hit, not to mention that you'r app would have to load a new assembly into memory after each compile. With Reflection.Emit you can use the same assembly over and over, each time you need to add a new dynamic class. The general rules with dynamic types is to code against a public interface. This is because you wont have any API to code against at design time. You should probably wrap your type builder logic in a class factory design pattern. This is useful since you wont be able to "new" a dynamic type. Like I said before, if you have any specific questions let me know and I'd be more than happy to help. Dynamic types are pretty cool to use. "Piggy" wrote: Thank you Jon. I am looking at the System.Reflection.Emit and System.CodeDom namespaces "Jon Skeet [C# MVP]" wrote: Piggy <Piggy (AT) discussions (DOT) microsoft.com> wrote: thank you very much for your reply. My problem is not about creating an instance of a type I am already doing this, now I would like to create dinamically a new type that inherit directly from the base class. The new type has to override a function of the base type, and the code of the override is to be provided by the user at runtime. I also need to save the new class. Ah, I see. In that case, you should look at the System.Reflection.Emit namespace and the System.CodeDom namespace. Both should have a fair amount of documentation and examples in MSDN. -- Jon Skeet - <skeet (AT) pobox (DOT) com http://www.pobox.com/~skeet If replying to the group, please do not mail me too |
#9
| |||
| |||
|
|
Hi Piggy, Just to correct your code example the first statement of LoadClass should use LoadFrom instead of LoadFile ------------------------------------- Public Function LoadClass() Dim sperem As [Assembly] = [Assembly].LoadFrom("d:\tests\Prova.dll") ------------------------------------- Hope it will save some debugging time of the readers who wants to try this code. -- Cheers, Rahul Anand "Piggy" wrote: Hi John, I decided for the VBCodeProvider because I need to provide an editor functionality to my project. Only the user (obviously at runtime) decides how to override the critical function of the base class from which the new type will inherit. To do this I used the CodeSnippetUnit type to get the input text and VBCodeProvider to: 1-Generate the code 2-Save the code 3-Compile a new dll with the newly created type After creating the dll, I can load it throught Assembly.LoadFromFile. Working with the type is now easy, since it inherits from the base class I created in the main assembly. As for the problem of loading an assembly for each new class I (hope) it will not be a problem, only one of the new classes will be loaded of each operation. The following is the code I wrote. what do you think about it? Public Sub SaveCode() Dim LiteralCode As String = "Imports Microsoft.VisualBasic" & vbCrLf & "Imports FinancialFormulas" & vbCrLf & CodeRTF.Text '<<-- In CodeRTF (RichTextBox) the user writes the main code for the new class Dim CSU As New CodeSnippetCompileUnit(LiteralCode) Dim CodeWriter As IO.TextWriter = IO.File.CreateText("d:\tests\Prova.vb") Dim GOpts As New CodeGeneratorOptions Dim VBCoder As New VBCodeProvider Dim CGen As ICodeGenerator = VBCoder.CreateGenerator() CSU.ReferencedAssemblies.Add("System") CSU.ReferencedAssemblies.Add("Microsoft.VisualBasi c") CSU.ReferencedAssemblies.Add("C:\VBProgies\NET\Opt ions\OptionFormulas\bin\FinancialFormulas.dll") GOpts.ElseOnClosing = True CGen.GenerateCodeFromCompileUnit(CSU, CodeWriter, New System.CodeDom.Compiler.CodeGeneratorOptions) CodeWriter.Close() 'CodeRTF.LoadFile("d:\tests\Prova.vb") End Sub Public Function AddClass() As Boolean Dim VBCoder As New VBCodeProvider Dim CComp As ICodeCompiler = VBCoder.CreateCompiler Dim CParams As New CompilerParameters Dim EEn As IEnumerator If IO.File.Exists("d:\tests\Prova.dll") Then IO.File.Delete("d:\tests\Prova.dll") CParams.GenerateExecutable = False CParams.OutputAssembly = "d:\tests\Prova.dll" CParams.ReferencedAssemblies.Add("C:\VBProgies\NET \Options\OptionFormulas\bin\FinancialFormulas.dll" ) Dim Res As CompilerResults = CComp.CompileAssemblyFromFile(CParams, "d:\tests\Prova.vb") With Res If .Errors.Count <> 0 Then CodeRTF.Text &= vbCrLf & vbCrLf & "ERRORS FOUND!" & vbCrLf EEn = .Errors.GetEnumerator EEn.Reset() While EEn.MoveNext With CType(EEn.Current, CompilerError) CodeRTF.Text &= .ErrorText & " (Row " & .Line & ")" & vbCrLf End With End While Return False End If End With Return True End Function Public Function LoadClass() Dim sperem As [Assembly] = [Assembly].LoadFile("d:\tests\Prova.dll") Dim DynStrat As Type = sperem.GetType("DynInd") Dim Params() As Type = {GetType(String), GetType(String), GetType(Double), GetType(Double), GetType(FinancialFormulas.EquityPortfolioStrategie s.SingleIndexStrategy.MembersNumberMethodEnum), GetType(Integer)} Dim Values() As Object = {"Albert", "SX5E", CDbl(1000000000), CDbl(15), CType(0, FinancialFormulas.EquityPortfolioStrategies.Single IndexStrategy.MembersNumberMethodEnum), CType(13, Integer)} Dim CInfo As ConstructorInfo = DynStrat.GetConstructor(Params) Dim Strat As Object Try Strat = CInfo.Invoke(Values) Catch ex As Exception End Try MsgBox(Strat.GetTargetPortfolio(Now.Date)) End Function Thank you very much "john conwell" wrote: Hey Piggy, I'm in the middle of writing several articles on creating dynamic types at runtime so I can help you with any specific questions you have. First, yes, you'll have to use Reflection.Emit. the annoying thing about that is that you have to emit IL opcodes into your type TypeBuilder. You could build a string of C# or VB and then run it through the CSharpCodeProvider or VBCodeProvider object to compile it, but this would be a fairly big perf hit, not to mention that you'r app would have to load a new assembly into memory after each compile. With Reflection.Emit you can use the same assembly over and over, each time you need to add a new dynamic class. The general rules with dynamic types is to code against a public interface. This is because you wont have any API to code against at design time. You should probably wrap your type builder logic in a class factory design pattern. This is useful since you wont be able to "new" a dynamic type. Like I said before, if you have any specific questions let me know and I'd be more than happy to help. Dynamic types are pretty cool to use. "Piggy" wrote: Thank you Jon. I am looking at the System.Reflection.Emit and System.CodeDom namespaces "Jon Skeet [C# MVP]" wrote: Piggy <Piggy (AT) discussions (DOT) microsoft.com> wrote: thank you very much for your reply. My problem is not about creating an instance of a type I am already doing this, now I would like to create dinamically a new type that inherit directly from the base class. The new type has to override a function of the base type, and the code of the override is to be provided by the user at runtime. I also need to save the new class. Ah, I see. In that case, you should look at the System.Reflection.Emit namespace and the System.CodeDom namespace. Both should have a fair amount of documentation and examples in MSDN. -- Jon Skeet - <skeet (AT) pobox (DOT) com http://www.pobox.com/~skeet If replying to the group, please do not mail me too |
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
| |