public class SampleResponseModel { public string Message { get ; set ; } public bool Success { get ; set ; } public string CurrentTime { get ; set ; } }
public class SampleResponseModel { public string Message { get ; set ; } public bool Success { get ; set ; } public string CurrentTime { get ; set ; } }
public class SampleResponseModel { public string Message { get ; set ; } public bool Success { get ; set ; } public string CurrentTime { get ; set ; } }
public class SampleResponseModel { public string Message { get ; set ; } public bool Success { get ; set ; } public string CurrentTime { get ; set ; } }
public class SampleResponseModel { public string Message { get ; set ; } public bool Success { get ; set ; } public string CurrentTime { get ; set ; } }
public class SampleResponseModel { public string Message { get ; set ; } public bool Success { get ; set ; } public string CurrentTime { get ; set ; } }
- public class JQueryController : Controller
- {
- public ActionResult SimpleIntMethod ( )
- {
- return Json ( new Random ( ) . Next ( 100 ) ) ;
- }
- public ActionResult MethodWithParameters ( int num, string s, bool boolValue )
- {
- return Json ( string . Format ( "{0} - {1} - {2}" , num, s, boolValue ) ) ;
- }
- public ActionResult ReturningObject ( )
- {
- var result = new SampleResponseModel ( )
- {
- CurrentTime = DateTime . Now . ToLongTimeString ( ) ,
- Message = "Hello!" ,
- Success = true
- } ;
- return Json ( result ) ;
- }
- public ActionResult ReturningObjectWithParameters ( string echo )
- {
- var result = new SampleResponseModel ( )
- {
- CurrentTime = DateTime . Now . ToLongTimeString ( ) ,
- Message = echo,
- Success = true
- } ;
- return Json ( result ) ;
- }
- public ActionResult VoidMethodWithParameters ( SampleResponseModel model )
- {
- return null ;
- }
- }
- module Reinforced. Typings . Samples . Difficult . CodeGenerators . Pages {
- export class IndexPage {
- constructor ( ) {
- $ ( '#btnSimpleInt' ) . click ( this . btnSimpleIntClick . bind ( this ) ) ;
- $ ( '#btnMethodWithParameters' ) . click ( this . btnMethodWithParametersClick . bind ( this ) ) ;
- $ ( '#btnReturningObject' ) . click ( this . btnReturningObjectClick . bind ( this ) ) ;
- }
- private btnSimpleIntClick ( ) { }
- private btnMethodWithParametersClick ( ) { }
- private btnReturningObjectClick ( ) { }
- }
- }
- < span id = "loading" > < / span >
- Result: < strong id = "result" > < / strong >
- < button class = "btn btn-primary" id = "btnSimpleInt" > Tynts < / button >
- < button class = "btn btn-default" id = "btnMethodWithParameters" > Klac < / button >
- < button class = "btn btn-default" id = "btnReturningObject" > Bums < / button >
- < button class = "btn btn-default" id = "btnReturningObjectWithParameters" > Bidd < / button >
- < button class = "btn btn-default" id = "btnVoidMethodWithParameters" > Quack! < / button >
- @section Scripts
- {
- < script type = "text / javascript" src = "/Scripts/IndexPage.js" > < / script >
- < script type = "text / javascript" src = "/Scripts/query.js" > < / script >
- < script type = "text / javascript" >
- $ (document) .ready (function () {
- var a = new Reinforced.Typings.Samples.Difficult.CodeGenerators.Pages.IndexPage ();
- })
- < / script >
- }
- class QueryController {
- public static query < T > ( url : string , data : any , progressSelector : string , disableSelector : string = '' ) : JQueryPromise < T > {
- var promise = jQuery. Deferred ( ) ;
- var query = {
- data : JSON. stringify ( data )
- type : 'post' ,
- dataType : 'json' ,
- contentType : 'application / json' ,
- timeout : 9000000
- traditional : false ,
- complete : ( ) => {
- if ( progressSelector && progressSelector. length > 0 ) {
- $ ( progressSelector ) . find ( 'span [data-role = "progressContainer"]' ) . remove ( ) ;
- }
- if ( disableSelector && disableSelector. length > 0 ) {
- $ ( disableSelector ) . prop ( 'disabled' , false ) ;
- }
- } ,
- success : ( response : T ) => {
- promise. resolve ( response ) ;
- } ,
- error : ( request , status , error ) => {
- promise. reject ( { Success : false , Message : error. toString ( ) , Data : error } ) ;
- }
- } ;
- if ( progressSelector && progressSelector. length > 0 ) {
- $ ( progressSelector ) . append ( '<span data-role = "progressContainer"> Loading ... </ span>' ) ;
- }
- if ( disableSelector && disableSelector. length > 0 ) {
- $ ( disableSelector ) . prop ( 'disabled' , true ) ;
- }
- $. ajax ( url , < any > query ) ;
- return promise ;
- }
- }
- public class JQueryMethodAttribute : TsFunctionAttribute
- {
- public JQueryMethodAttribute ( Type returnType )
- {
- StrongType = returnType ;
- CodeGeneratorType = typeof ( JQueryActionCallGenerator ) ;
- }
- }
- [ TsClass ]
- public class JQueryController : Controller
- {
- [ JQueryMethod ( typeof ( int ) ) ]
- public ActionResult SimpleIntMethod ( )
- {
- // fold
- }
- [ JQueryMethod ( typeof ( string ) ) ]
- public ActionResult MethodWithParameters ( int num, string s, bool boolValue )
- {
- // fold
- }
- [ JQueryMethod ( typeof ( SampleResponseModel ) ) ]
- public ActionResult ReturningObject ( )
- {
- // fold
- }
- [ JQueryMethod ( typeof ( SampleResponseModel ) ) ]
- public ActionResult ReturningObjectWithParameters ( string echo )
- {
- // fold
- }
- [ JQueryMethod ( typeof ( void ) ) ]
- public ActionResult VoidMethodWithParameters ( SampleResponseModel model )
- {
- // fold
- }
- }
- [ TsInterface ]
- public class SampleResponseModel
- {
- // fold
- }
- using System ;
- using System.Linq ;
- using System.Reflection ;
- using Reinforced.Typings.Ast ;
- using Reinforced.Typings.Generators ;
- /// <summary>
- /// Our code generator for wrappers on calls to the controller method.
- /// It is sharpened to take MethodInfo as input and produce as output
- /// instance of RtFunction, which is a piece of the syntax tree
- /// with TypeScript.
- /// As mentioned above, we inherit from the built-in RT MethodCodeGenerator,
- /// which normally generates a method with a signature and an empty implementation
- /// </ summary>
- public class JQueryActionCallGenerator : MethodCodeGenerator
- {
- /// <summary>
- /// Naturally, we overload the GenerateNode method. Actually, it is almost the only
- /// and the main method in the code generator.
- /// </ summary>
- /// <param name = "element"> Method for which code will be generated as MethodInfo </ param>
- /// <param name = "result">
- /// Result AST-node (RtFunction).
- /// We do not create a node from scratch. And to be honest, I forgot why I made such an architectural decision :)
- /// But we can still return null to exclude the node / method from the final TypeScript file
- /// </ param>
- /// <param name = "resolver">
- /// And this is an instance of TypeResolver. This is a special class that we can use.
- /// to display types in the resulting TypeScript, so as not to do anything by hand.
- /// </ param>
- /// <returns> RtFunction (also known as the syntax tree node, also known as the AST node) </ returns>
- public override RtFuncion GenerateNode ( MethodInfo element, RtFuncion result, TypeResolver resolver )
- {
- // First, generate the "as usual" method wrapper
- // Next, we will expand and complement it
- result = base . GenerateNode ( element, result, resolver ) ;
- // If for some reason an empty node is generated, then it should be
- // we will not interfere in this process
- if ( result == null ) return null ;
- // Make our method static
- result . IsStatic = true ;
- // And also add a couple of extra parameters to the method to specify
- // element that will be disabled while the server method is being called,
- // as well as the element to which the loading indicator should be added
- result . Arguments . Add (
- new RtArgument ( )
- {
- Identifier = new RtIdentifier ( "loadingPlaceholderSelector" ) ,
- Type = resolver . ResolveTypeName ( typeof ( string ) ) ,
- DefaultValue = "''"
- } ) ;
- result . Arguments . Add (
- new RtArgument ( )
- {
- Identifier = new RtIdentifier ( "disableElement" ) ,
- Type = resolver . ResolveTypeName ( typeof ( string ) ) ,
- DefaultValue = "''"
- } ) ;
- // Store the original method return value
- // for further we need to parameterize it with jQueryPromise
- var retType = result . ReturnType ;
- // ... and if the return type is void, we just leave JQueryPromise <any>
- bool isVoid = ( retType is RtSimpleTypeName ) && ( ( ( RtSimpleTypeName ) retType ) . TypeName == "void" ) ;
- // here I use TypeResolver to get an AST node for the name of the type "any"
- // just to demonstrate the use of TypeResolver
- // (well, also because I'm lazy enough to create with any hands)
- if ( isVoid ) retType = resolver . ResolveTypeName ( typeof ( object ) ) ;
- // OK, redefine the return value of our method, wrapping it
- // in jQueryPromise
- // We use the RtSimpleType class, passing generic arguments to it,
- // so as not to write angle brackets
- result . ReturnType = new RtSimpleTypeName ( "JQueryPromise" , new [ ] { retType } ) ;
- // Now it's up to the parameters. We get them through reflection.
- // Next, we use the extension. GetName () to get the name of the parameter
- // This extension comes with Reinforced.Typings and returns the name of the parameter.
- // method with all potential overloads via Fluent configuration or
- // attribute [TsParameter]
- var p = element . GetParameters ( ) . Select ( c => string . Format ( "'{0}': {0}" , c . GetName ( ) ) ) ;
- // Link parameters to generate method body code
- var dataParameters = string . Join ( "," , p ) ;
- // Get the path to the controller
- // Here we have a simple solution that requires having a MVC route on / {controller} / {action}
- // it is assumed that he is (although whom I cheat, he is in 90% of applications)
- string controller = element . DeclaringType . Name . Replace ( "Controller" , String . Empty ) ;
- string path = String . Format ( "/ {0} / {1}" , controller, element . Name ) ;
- // Now let's create a glue-code with a call to QueryController, which we defined in query.ts
- string code = String . Format (
- @ "return QueryController.query <{2}> (
- '{0}',
- {{ {one} }},
- loadingPlaceholderSelector,
- disableElement
- ); " ,
- path, dataParameters, retType ) ;
- // Wrap the code in RtRaw and stuff as the body into our result
- result . Body = new RtRaw ( code ) ;
- // Now let's add some JSDOC to make the results of our work more obvious.
- result . Documentation = new RtJsdocNode ( ) { Description = String . Format ( "Wrapper method for call {0} of {1}" , element . Name , element . DeclaringType . Name ) } ;
- // Actually, that's all. Return RtFunction
- // According to the default settings of the config, this good will be recorded in the project.ts
- return result ;
- }
- }
- module Reinforced. Typings . Samples . Difficult . CodeGenerators . Models {
- export interface ISampleResponseModel
- {
- Message : string ;
- Success : boolean ;
- CurrentTime : string ;
- }
- }
- module Reinforced. Typings . Samples . Difficult . CodeGenerators . Controllers {
- export class jQueryController
- {
- / ** Wrapper method for call SimpleIntMethod of JQueryController * /
- public static SimpleIntMethod ( loadingPlaceholderSelector : string = '' , disableElement : string = '' ) : JQueryPromise < number >
- {
- return QueryController. query < number > (
- '/ JQuery / SimpleIntMethod' ,
- { }
- loadingPlaceholderSelector ,
- disableElement
- ) ;
- }
- / ** Wrapper method for call MethodWithParameters of JQueryController * /
- public static MethodWithParameters ( num : number , s : string , boolValue : boolean , loadingPlaceholder : string : string = '' , disableElement : string = '' ) : JQueryPromise < string >
- {
- return QueryController. query < string > (
- '/ JQuery / MethodWithParameters' ,
- { 'num' : num , 's' : s , 'boolValue' : boolValue } ,
- loadingPlaceholderSelector ,
- disableElement
- ) ;
- }
- / ** Wrapper method for call ReturningObject of JQueryController * /
- public static ReturningObject ( loadingPlaceholderSelector : string = '' , disableElement : string = '' ) : JQueryPromise < Reinforced. Typings . Samples . Difficult . CodeGenerators . Models . ISampleResponseModel >
- {
- return QueryController. query < Reinforced. Typings . Samples . Difficult . CodeGenerators . Models . ISampleResponseModel > (
- '/ JQuery / ReturningObject' ,
- { }
- loadingPlaceholderSelector ,
- disableElement
- ) ;
- }
- / ** Wrapper method for call ReturningObjectWithParameters of JQueryController * /
- public static ReturningObjectWithParameters ( echo : string , loadingPlaceholderSelector : string = '' , disableElement : string = '' ) : JQueryPromise < Reinforced. Typings . Samples . Difficult . CodeGenerators . Models . ISampleResponseModel >
- {
- return QueryController. query < Reinforced. Typings . Samples . Difficult . CodeGenerators . Models . ISampleResponseModel > (
- '/ JQuery / ReturningObjectWithParameters' ,
- { 'echo' : echo } ,
- loadingPlaceholderSelector ,
- disableElement
- ) ;
- }
- / ** Wrapper method for call VoidMethodWithParameters of JQueryController * /
- public static VoidMethodWithParameters ( model : Reinforced. Typings . Samples . Difficult . CodeGenerators . Models . ISampleResponseModel , loadingPlaceholderSelector : string = '' , disableElement : string = '' ) : JQueryPromise < any >
- {
- return QueryController. query < any > (
- '/ JQuery / VoidMethodWithParameters' ,
- { 'model' : model } ,
- loadingPlaceholderSelector ,
- disableElement
- ) ;
- }
- }
- }
- module Reinforced. Typings . Samples . Difficult . CodeGenerators . Pages {
- import JQueryController = Reinforced. Typings . Samples . Difficult . CodeGenerators . Controllers . JQueryController ;
- export class IndexPage {
- constructor ( ) {
- $ ( '#btnSimpleInt' ) . click ( this . btnSimpleIntClick . bind ( this ) ) ;
- $ ( '#btnMethodWithParameters' ) . click ( this . btnMethodWithParametersClick . bind ( this ) ) ;
- $ ( '#btnReturningObject' ) . click ( this . btnReturningObjectClick . bind ( this ) ) ;
- $ ( '#btnReturningObjectWithParameters' ) . click ( this . btnReturningObjectWithParametersClick . bind ( this ) ) ;
- $ ( '#btnVoidMethodWithParameters' ) . click ( this . btnVoidMethodWithParametersClick . bind ( this ) ) ;
- }
- private btnSimpleIntClick ( ) {
- JQueryController. SimpleIntMethod ( '#loading' , '#btnSimpleInt' )
- . then ( r => $ ( '#result' ) . html ( 'Server tells us' + r ) ) ;
- }
- private btnMethodWithParametersClick ( ) {
- JQueryController. MethodWithParameters ( Math. Random ( ) , 'string' + Math. Random ( ) , Math. Random ( ) > 0.5 , '#loading' , '#btnMethodWithParameters' )
- . then ( r => {
- $ ( '#result' ) . html ( r ) ;
- } ) ;
- }
- private btnReturningObjectClick ( ) {
- JQueryController. ReturningObject ( '#loading' , '#btnReturningObject' )
- . then ( r => {
- var s = "<pre> {<br/>" ;
- for ( var key in r ) {
- s + = `$ { key } : $ { r [ key ] } , \ n` ;
- }
- s + = '} </ pre>' ;
- $ ( '#result' ) . html ( s ) ;
- } ) ;
- }
- private btnReturningObjectWithParametersClick ( ) {
- var str = 'Random number:' + Math. random ( ) * 100 ;
- JQueryController. ReturningObjectWithParameters ( str , '#loading' , '#btnReturningObjectWithParameters' )
- . then ( r => {
- var s = "<pre> {<br/>" ;
- for ( var key in r ) {
- s + = `$ { key } : $ { r [ key ] } , \ n` ;
- }
- s + = '} </ pre>' ;
- $ ( '#result' ) . html ( s ) ;
- } ) ;
- }
- private btnVoidMethodWithParametersClick ( ) {
- JQueryController. VoidMethodWithParameters ( {
- Message : 'Hello' ,
- Success : true
- CurrentTime : null
- } , '#loading' , '#btnVoidMethodWithParameters' )
- . then ( ( ) => {
- $ ( '#result' ) . html ( 'not return result' ) ;
- } ) ;
- }
- }
- }
- using System ;
- using System.Linq ;
- using System.Reflection ;
- using Reinforced.Typings.Ast ;
- using Reinforced.Typings.Generators ;
- /// <summary>
- /// Generator wrapper methods for angular.js
- /// </ summary>
- public class AngularActionCallGenerator : MethodCodeGenerator
- {
- public override RtFuncion GenerateNode ( MethodInfo element, RtFuncion result, TypeResolver resolver )
- {
- result = base . GenerateNode ( element, result, resolver ) ;
- if ( result == null ) return null ;
- // overload the type of method under our promise
- var retType = result . ReturnType ;
- bool isVoid = ( retType is RtSimpleTypeName ) && ( ( ( RtSimpleTypeName ) retType ) . TypeName == "void" ) ;
- // exactly the same trick with void methods
- if ( isVoid ) retType = resolver . ResolveTypeName ( typeof ( object ) ) ;
- // use angular.IPromise instead of jQueryPromise
- result . ReturnType = new RtSimpleTypeName ( new [ ] { retType } , "angular" , "IPromise" ) ;
- // method parameters - by the same principle
- var p = element . GetParameters ( ) . Select ( c => string . Format ( "'{0}': {0}" , c . GetName ( ) ) ) ;
- var dataParameters = string . Join ( "," , p ) ;
- // Get the path to the controller
- string controller = element . DeclaringType . Name . Replace ( "Controller" , String . Empty ) ;
- string path = String . Format ( "/ {0} / {1}" , controller, element . Name ) ;
- // Generate code via this.http.post
- const string code = @ "var params = {{{1}}};
- return this.http.post ('{0}', params)
- .then ((response) => {{return response.data;}}); " ;
- // also wrapped in RtRaw
- RtRaw body = new RtRaw ( String . Format ( code, path, dataParameters ) ) ;
- result . Body = body ;
- return result ;
- }
- }
- using System ;
- using Reinforced.Typings.Ast ;
- using Reinforced.Typings.Generators ;
- /// <summary>
- /// A generator that wraps our methods in an angular service.
- /// inherit from the standard class generator
- /// </ summary>
- public class AngularControllerGenerator : ClassCodeGenerator
- {
- public override RtClass GenerateNode ( Type element, RtClass result, TypeResolver resolver )
- {
- // Again, start with the "standard" class generated for the controller
- result = base . GenerateNode ( element, result, resolver ) ;
- if ( result == null ) return null ;
- // Add some documentation
- result . Documentation = new RtJsdocNode ( ) { Description = "Result of AngularControllerGenerator activity" } ;
- // create the type name angular.IHttpService
- var httpServiceType = new RtSimpleTypeName ( "IHttpService" ) { Namespace = "angular" } ;
- // Add a constructor, ...
- RtConstructor constructor = new RtConstructor ( ) ;
- // ... host $ http: angular.IHttpService
- constructor . Arguments . Add ( new RtArgument ( ) { Type = httpServiceType, Identifier = new RtIdentifier ( "$ http" ) } ) ;
- // his body will contain a single line -
- // $http
- constructor . Body = new RtRaw ( "this.http = $http;" ) ;
- // , $http
- RtField httpServiceField = new RtField ( )
- {
- Type = httpServiceType,
- Identifier = new RtIdentifier ( "http" ) ,
- AccessModifier = AccessModifier . Private ,
- Documentation = new RtJsdocNode ( ) { Description = " $http " }
- } ;
- //
- result . Members . Add ( httpServiceField ) ;
- result . Members . Add ( constructor ) ;
- // ,
- // Api.%Something%Controller
- const string initializerFormat =
- "if (window['app']) window['app'].factory('Api.{0}', ['$http', ($http: angular.IHttpService) => new {1}($http)]);" ;
- //
- RtRaw registration = new RtRaw ( String . Format ( initializerFormat,element . Name ,result . Name ) ) ;
- // ( Context),
- // Context.Location.CurrentModule.CompilationUnits
- // CompilationUnits RtNode,
- // , RtRaw
- // ,
- Context . The Location . CurrentModule . CompilationUnits . Add ( registration ) ;
- return result ;
- }
- }
- module Reinforced. Typings . Samples . Difficult . CodeGenerators . Controllers {
- if ( window [ 'app' ] ) window [ 'app' ] . factory ( 'Api.AngularController' , [ '$http' , ( $http : ng. IHttpService ) => new AngularController ( $http ) ] ) ;
- /** Result of AngularControllerGenerator activity */
- export class AngularController
- {
- constructor ( $http : ng. IHttpService )
- {
- this . http = $http ;
- }
- public SimpleIntMethod ( ) : ng. IPromise < number >
- {
- var params = { } ;
- return this . http . post ( '/Angular/SimpleIntMethod' , params )
- . then ( ( response ) => { response. data [ 'requestParams' ] = params ; return response. data ; } ) ;
- }
- public MethodWithParameters ( num : number , s : string , boolValue : boolean ) : ng. IPromise < string >
- {
- var params = { 'num' : num , 's' : s , 'boolValue' : boolValue } ;
- return this . http . post ( '/Angular/MethodWithParameters' , params )
- . then ( ( response ) => { response. data [ 'requestParams' ] = params ; return response. data ; } ) ;
- }
- public ReturningObject ( ) : ng. IPromise < Reinforced. Typings . Samples . Difficult . CodeGenerators . Models . ISampleResponseModel >
- {
- var params = { } ;
- return this . http . post ( '/Angular/ReturningObject' , params )
- . then ( ( response ) => { response. data [ 'requestParams' ] = params ; return response. data ; } ) ;
- }
- public ReturningObjectWithParameters ( echo : string ) : ng. IPromise < Reinforced. Typings . Samples . Difficult . CodeGenerators . Models . ISampleResponseModel >
- {
- var params = { 'echo' : echo } ;
- return this . http . post ( '/Angular/ReturningObjectWithParameters' , params )
- . then ( ( response ) => { response. data [ 'requestParams' ] = params ; return response. data ; } ) ;
- }
- public VoidMethodWithParameters ( model : Reinforced. Typings . Samples . Difficult . CodeGenerators . Models . ISampleResponseModel ) : ng. IPromise < any >
- {
- var params = { 'model' : model } ;
- return this . http . post ( '/Angular/VoidMethodWithParameters' , params )
- . then ( ( response ) => { response. data [ 'requestParams' ] = params ; return response. data ; } ) ;
- }
- / ** Keeps $ http instance received on construction * /
- private http : ng. IHttpService ;
- }
- }
Source: https://habr.com/ru/post/278961/
All Articles