Start a new topic

JS(Name)... When to use "Object" and when to use class name

What is the rule of thumb when making bindings to name the JS attribute?


For libs like JQuery... I use "Object" for everything UNLESS is static class, then i use the class name (Or namespace name)...


When converting other libs like Phaser where there should be an actual class like Phaser.Game ... I use "Object" unless the class has a "constructor" ... so it can be 'new' up... Then i use the Full Namespace and class name like "Phaser.Game"


What it rule... when should i use objected when should i use an actual name?



Good starting point is always too look at .d.ts declaration file.

You mention Phaser, so let's look at:

https://github.com/photonstorm/phaser/blob/master/typescript/phaser.d.ts


For example Animation is class with constructor, translates to C# [Js(Extern = true)] class with extern ctor (no need to renamed it, as you wrote above).

Game is also a class with constructor(s), translates to C# [Js(Extern = true)] class with extern ctor.


Device is also a class but with extern private constructor (you can't and should not create an instance of it), it has some extern properties some static and some not, like this:

  

[Js(Extern = true)]
public class Device {

        public static bool LITTLE_ENDIAN { get; }
        
        public static extern void checkFullScreenSupport();
        public static extern bool canPlayAudio(type: string);
        ...

        public bool android { get; set; }
        public bool arora: boolean  { get; set; }
        ...

        private extern Device();
}

  


interface IGameConfig is a TypeScript so called record/interface class, so in C# define it is a class inherited from JsInterface. You want to create it easily and pass to Game ctor.


One more tip, we strongly recommend to minimize use of JsAttribute as much as you can, so the C# d.cs file will look very clean and easy to read.

Deployment and distribution of d.cs files should as is no need to wrap them as a class assembly, thus their usage is very convenient, similar to TypeScript, just add a single file (even as a link) to your C# project.


Hopes this help.



Very kool...


What about delegates and enums created to support the the binding api... Should they ever have a JSName or just the [Js(Extern=true)]

Also ... Should enum have some kind of subclassing like interface should be made a JsInterface subclass?

interface IGameConfig is a TypeScript so called record/interface class, so in C# define it is a class inherited from JsInterface. You want to create it easily and pass to Game actor.


Should that also have [Js(Extern=true)]?


Example


[Js(Extern=true)]

public class IGameConfig : JsInterface

{

...

}


AND DELEGATES


[Js(Extern=true)]

public delegate void DoSomthing();



AND ENUMS


[Js(Extern=true)]

public enum TestOptions

{

...

}

PROBLEM ENCOUNTERED


[Js(Extern=true)]

public class IGameConfig : JsInterface

{

...

}


What if the interface already extends something... Cant have a class that sub subclass more than one... so cant use JSInterface

[Js(Extern=true)] is not needed on class inherited from JsDictionary or JsInterface, it's auto deducted by the compiler.


[Js(Extern=true)] is need on external delegates

public delegate void DoSomething();


[Js(Extern=true)] is needed on external enums, but only if enums are integers with known values at compile time

public enum TestOptions


keep in mind that sometimes JS enums values are properties, thus define them in C# as a static extern properties getter only of some extern class class.


[Js(Extern=true)] is needed on extern multiple interfaces.



Regarding: Device is also a class but with extern private constructor (you can't and should not create an instance of it), it has some extern properties some static and some not, like this:

 

I have created binding that adhere to the rules above, Take for example Phaser.State:

 

	[Js(Name="Phaser.State", Extern=true)]
	public class State
	{
		#pragma warning disable CS0824
		extern State();
		#pragma warning restore CS0824
		public Phaser.GameObjectFactory add { get; set; }
		public Phaser.Cache cache { get; set; }
		public Phaser.Camera camera { get; set; }
		public Phaser.Game game { get; set; }
		public Phaser.Input input { get; set; }
		public string key { get; set; }
		public Phaser.Loader load { get; set; }
		public Phaser.GameObjectCreator make { get; set; }
		public Phaser.ParticlesClass particles { get; set; }
		public Phaser.PhysicsClass physics { get; set; }
		public Phaser.RandomDataGenerator rnd { get; set; }
		public Phaser.ScaleManager scale { get; set; }
		public Phaser.SoundManager sound { get; set; }
		public Phaser.Stage stage { get; set; }
		public Phaser.Time time { get; set; }
		public Phaser.TweenManager tweens { get; set; }
		public Phaser.World world { get; set; }
		public extern virtual void create();
		public extern virtual void init(params any[] args);
		public extern virtual void loadRender();
		public extern virtual void loadUpdate();
		public extern virtual void paused();
		public extern virtual void pauseUpdate();
		public extern virtual void preload();
		public extern virtual void preRender();
		public extern virtual void render();
		public extern virtual void resize();
		public extern virtual void resumed();
		public extern virtual void shutdown();
		public extern virtual void update();
	}

 

This class had no constructors on it so i gave a private constructor... That means YOU CANT instance it or even sub-class it because the base class constructor not accessible.


But the Phaser TypeScript Tutorials ARE CLEARLY subclassing from Phaser.State... And even overriding methods like 'create'


How can that be. I thought type script was supposed to be string typed... How can have a base class with a private constructor and subclass it?






Login or Signup to post a comment