To improve performance in Blazor JS Interop calls, synchronous and unmarshalled apis are available
I struggle to find more information regarding the unmarshalled.
For example:
//javascript
JSFunctions.f1 = function (fields) {
var f1 = Blazor.platform.readStringField(fields, 0);
var f2 = Blazor.platform.readStringField(fields, 4);
var f3 = Blazor.platform.readStringField(fields, 8);
};
//F#
[<Inject>]
member val Js: IJSRuntime
let js = this.Js :?> IJSUnmarshalledRuntime
js.InvokeUnmarshalled<ElementReference, string, unit>("JSFunctions.f1", er, txt)
Where are the functions Blazor.platform.* defined?
Which one should be used to retrieve an argument of type ElementReference?
What is the second int parameter of the function readStringField and how should it be used?
Blazor object is a JavaScript object in global namespace (window) which added by blazor.webassembly.js in Blazor WebAssembly or blazor.server.js in Blazor Server. It added at the default template of Blazor Apps at the end of index.html (or _Host.cshtml) by following script:
<script autostart="false" src="_framework/blazor.webassembly.js"></script>
The Blazor object provide Blazor.platform and some useful api for example start() for manual start of Blazor.
This script also add another object named BINDING to global namespace (window.BINDING or simply BINDING).
They provide methods for working with .NET objects directly from JavaScript in unmarshalled way. for example you can read different type of data using
Blazor.platform.read....
You can read objects like ElementReference type object using:
Blazor.platform.readObjectField(fields,index)
Here fields is the input (struct or class) passed to JS function when you invoke it and index is its field offset in struct/class definition. You can read more about field offset in Microsoft documentations here.
Here is some example:
[StructLayout(LayoutKind.Explicit)]
public struct InteropStruct
{
[FieldOffset(0)]
public string Name;
[FieldOffset(8)]
public int Year;
}
You can also return a .Net object directly from JavaScript functions using BINDING as below:
return BINDING.js_string_to_mono_string(`Hello, ${name} (${year})!`);
You can discover more about these two objects in your browser developer tool for example by writing Blazor.platform. or BINDING.:
Related
I have a method in .NET (GetDataStationParts), which I declare with 2 parameters, I want to call it from a JavaScript, and I use the InvokeMethodAsyn function in this way:
const { data } = require("jquery");
function GetParteScrap()
{
var idestacionjs = document.getElementById('getestacion');
var idmodelojs = document.getElementById('getmodelo');
var tablascrap = DotNet.InvokeMethodAsyn("YMMScrapSystem", "GetDataStationParts", idestacionjs, idmodelojs);
console.log(tablascrap);
}
To do it, I base it on an example on the web but I'm not sure where it gets the DotNet object to then invoke the method, the intention of my code is that after selecting parameters of 2 , go to the database and execute a SQL-level function, which will return a table, with the function GetDataStationParts, I try to give it the functionality to execute my method at the DB level as follows
[JSInvokable]
public async Task<IEnumerable<GetEstacionParte>>GetDataStationParts(int modelo, int estacion)
{
var resul = await _context.Set<GetEstacionParte>().FromSqlInterpolated($"SELECT * FROM dbo.GetEstacionParte({modelo},{estacion})").ToArrayAsync();
return resul;
}
The SQL level function works correctly, but when running the application at the console level in the browser, it throws the following error, where it indicates that the function is not defined
Where could the error be? Thank you for reading
require() is not a feature that is built into the browser. Javascript environment does not understand how to handle require(), In Node.js by Default this function is available.
I suspect you most probably missing some reference here. You can either download require.js from here & link with your application or use below script tag.
<script src="https://requirejs.org/docs/release/2.3.5/minified/require.js"></script>
I am working though Petzold's Creating Mobile Apps Using Xamarin Forms book, translating the C# code into F# where the F# code is not available on GitHub (he stopped posting FS after chapter 7). In chapter 9, page 189, he makes use of the Dependency attribute like this:
[assembly: Dependency(typeof(DisplayPlatformInfo.iOS.PlatformInfo))]
namespace DisplayPlatformInfo.iOS
{
public interface IPlatformInfo
{
string GetModel();
string GetVersion();
}
using System;
using UIKit;
using Xamarin.Forms;
public class PlatformInfo : IPlatformInfo
{
UIDevice device = new UIDevice();
//etc...
I want to do the equivalent in F#. I created the type and the only place I can add that attribute is at a generic do() statement:
type PlatformInfo () =
[<assembly: Dependency(typeof(Greetings.iOS.PlatformInfo))>]
do()
interface IPlatformInfo with
member this.GetModel () =
let device = new UIDevice()
device.Model.ToString()
member this.GetVersion () =
let device = new UIDevice()
String.Format("{0} {1}", device.SystemName, device.SystemVersion)
The problem is that I get a
warning: attributes are ignored in this construct.
How should I be placing this attribute into the type?
Assembly level attributes in F# need to be a in module, at the top level.
I would translate the C# above as:
namespace rec DisplayPlatformInfo.iOS
// Make a module specifically for this attribute
module DisplayPlatformAssemblyInfo =
[<assembly: Dependency(typeof(Greetings.iOS.PlatformInfo))>]
do ()
type IPlatformInfo =
abstract member GetModel : unit -> string
abstract member GetVersion : unit -> string
// ... Implement your type, etc
Since it is an assembly attribute, it should be place at the top level of a module instead of in a type. The following should be working:
[<assembly: Dependency(typeof(Greetings.iOS.PlatformInfo))>]
do ()
type PlatformInfo () =
// ...
here is the code of an alloy controller written in two different ways. Although the both work the same, Which one might be best practice?
example 1 of controller.js:
var currentState = true;
$.getState = function(){
return currentState;
}
example 2 of controller.js:
var currentState = true;
exports.getState = function(){
return currentState;
}
Titanium is based on the CommonJS framework. The exports variable is a special variable used typically to expose a public API in a class object. So when you want to expose a method of doSomething() on the MyModule.js class you would use the exports variable like this:
exports.doSomething() = function(args) {
//Some really cool method here
};
Then reference that class using
var myModule = require('MyModule');
myModule.doSomething();
However when referencing a view object the typical way to reference the is using the $. shortcut. You can see they prefer that method in the official documentation.
http://docs.appcelerator.com/platform/latest/#!/guide/Alloy_XML_Markup
The $ variable holds a reference to your controller instance. It also contains some references to all indexed views (understand, views for which you supplied an index in you xml markup).
Both ways are strictly equivalent as, during the compilation, Alloy will merge the content of the exports with your controller referenced in $. Adding them directly to the instance won't change a thing.
Neverthless, developers are used to see the public API as the set of functions exported via the special variable exports; Thus, I will recommend to keep using it in a clean and clear way (for instance, defining your functions in your module scope, and only expose them at the end or beginning of your controller).
function myFunction1 () { }
function myFunction2 () { }
function myFunction3 () { }
exports.myFunction1 = myFunction1;
exports.myFunction3 = myFunction3;
Thereby, your API is quite clear for people diving into your source code. (A readMe file is also highly recommended :) ).
I'm developing a HTML5 showcase application and I need to discover all the methods in my Swift protocols. All the protocols extends from a base protocol.
The application is a HTML5 showcase for testing this methods. The app calls the method and gives the response.
I found some information about one specific protocol but i need to discover all the protocols in my app and then all the information (name, arguments name arguments type and return values) about this methods.
#objc protocol Protocol {
func method1()
func method2() -> Bool
func method3(param1:Int) -> Bool
func method4(param1:Int, param2:Int, param3:Int) -> Bool
}
var numMethods:UInt32 = 0
var methods:UnsafeMutablePointer<objc_method_description> = protocol_copyMethodDescriptionList(Protocol.self, true, true, &numMethods)
for var iuint:CUnsignedInt = 0; iuint < numMethods; iuint++ {
var i:Int = Int(iuint)
var method:objc_method_description = methods[i]
println("Method #\(i): \(method.name)")
}
I'm using Objective-C Runtime Reference
Any ideas how to do this in swift?
You are going to want to get:
the method implementation (method_getImplementation) https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/c/func/method_getImplementation
and the method selector (method_getName) https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/c/func/method_getName
Then in objective-c (using a bridged file, of course), cast the method implementation (i.e. IMP) as a function pointer. Then call the function pointer in objective-c with the
target
selector
and any parameters you may have
id (*func)(id, SEL, id) = (void *)imp;
return func(target, selector, param);`
Take a look at how in this blog post he calls the init method and that should help as well.
http://ijoshsmith.com/2014/06/05/instantiating-classes-by-name-in-swift/
There is no real reflection in swift.
For more reading, please read:
Does Swift support reflection?
How do I print the type or class of a variable in Swift?
http://waffletower.blogspot.sg/2014/06/swift-doesnt-have-much-objective-c.html
https://github.com/mikeash/MAObjCRuntime
I am just learning actionscript, so come across the problem
In my application I often call to different web services, and because I don't want to hardcode urls to them in my code, I am passing urls to the services as flashvars.
Currently I am doing it this way:
public var siteUrl:String;
public var gameId:String;
public function main():void
{
siteUrl = Application.application.parameters.siteurl;
gameId = Application.application.parameters.gameid;
Where main is a function, which is called on application's creation complete event.
This way I can call both variables from main file of the application but I want to access them from other files. (other as classes)
So is there a way to create class with constants and init values there with flashvars so I can use them everywhere (after importing of course)
The parameters are just stored in that Application.application.parameters object, and that's static. There's no reason you couldn't access that from other classes in your code.
If you want to write a class that wraps the parameters (maybe validates them or something) you could do that fairly easily. You can use a for each loop to loop over all the parameters. Something like:
var params:Object = Application.application.parameters
for(var name:String in params) {
var value:String = params[name] as String;
/* do something with the param */
}
If you want your class to actually verify things then it could just check for each parameter it expects and store it in a local variable.
It really just depends on your own preferences. Some people are fine with accessing the parameters object when they need it. Some people like having the extra code-completion by having a config class that actually defines all the expected config variables.
Update in response to comment:
Instead of having one module declare the variable and have other modules have to depend on that one to access the property it would be cleaner to have a single config module that everything that needs it would all use.
You could use a static class or singleton or some IoC stuff. Just for simplicity I'll show you a way you can do it with a static class.
class MyConfig {
private static var _infoService:String;
private static var _someOtherParam:int;
public static function get infoService():String { return _infoService; }
public static function get someOtherParam():int { return _someOtherParam; }
public static function initParams():Void {
var params:Object = Application.application.parameters;
_infoService = params.infoservice;
// just assuming you have a method to convert here. don't remember the
// code off the top of my head
_someOtherParam = convertToInt(params.someOtherParam);
}
}
Make sure when your app initializes it calls MyConfig.initParams(). You can have that method actually validate that it gets everything it expects and throw exceptions (or return an error) if there's a failure if you want.
Then wherever you need to use that config within your code you just import your config class and access the param. So getting infoService would just be:
var infoService:String = MyConfig.infoService;
Personally I wouldn't use a static class, but it was the easiest to show.