How to create an instance from string name? - reflection

Similar to this question, but I'm looking for a Haxe 3.0 solution. I'm looking to instantiate a class based on a a string (from my data file).
As far as I can tell this is correct. However, I get a runtime error
[Fault] exception, information=No such constructor npc.NPC_Squid
Fault, createEnum() at Type.hx:166
The Haxe 3 Code:
var e = haxe.macro.Expr.ExprDef;
var instance :Dynamic = e.createByName( "npc." + data.character, [] );
//....
My class:
package npc;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import openfl.Assets;
class NPC_Squid extends Sprite
{
public function new()
{
super();
addEventListener( Event.ADDED_TO_STAGE, onAdded);
addEventListener( Event.REMOVED_FROM_STAGE, onRemoved);
}
//....
My packages seem correct. Any ideas as to why it can't find the constructor?

I think you would need this:
var myInstance = Type.createInstance(Type.resolveClass("mypackage.MyClass"));
Note if you use dead-code elimination, you should import/reference MyClass somewhere.
I mostly create a function forceCompile in my Main class for such things:
public static function main()
{
forceCompile();
// Wind up all your stuff
}
public static function forceCompile()
{
MyClass;
}

In my Haxe 3 project, I use:
var easing: IEasing = Type.createEmptyInstance(Type.resolveClass("motion.easing." + easingType + easingStyle));
And it worked perfectly. One important precision: you need to import all the class that can be created this way. I imported all my motion.easing package to be sure.
You can see the full example here

Related

How to pass my viewmodel to a class that does not extend activity

How to pass my viewmodel to a class that does not extend activity
I'm calling my viewmodel like this:
in my EntryAbstract class
where am I going wrong
val FrutasViewModel = ViewModelProvider.NewInstanceFactory().create(FrutasViewModel::class.java)
FrutasViewModel.frutaData.value.forEach { item->
itens.add(ShoppingCart
(id=item.id,photo=item.photo,
name=item.name,quantidade=item.quantidade
,categoria = item.categoria,descricao = item.descricao
,unidade=item.unidade,kilo = item.kilo
))
}
my viewmodel:
package com.example.quitanda.models
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class FrutasViewModel(
private val frutasServices: Services,
):ViewModel() {
private val _frutasData: MutableStateFlow<List<ShoppingCart>> = MutableStateFlow<List<ShoppingCart>>(listOf<ShoppingCart>(ShoppingCart()))
val frutaData: StateFlow<List<ShoppingCart>>
get() = _frutasData
fun getFrutas(){
viewModelScope.launch {
try {
val frutas = frutasServices.getFruta()
_frutasData.value = frutas
}catch (e:Exception){
Log.d("Service error",e.toString())
}
}
}
}
My service:
package com.example.quitanda.models
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET
interface Services {
#GET("/category/7")
suspend fun getFruta(
//#Query("apikey")
//apikey:String = "333b4285"
): List<ShoppingCart>
}
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl("http://localhost:4000/")
.addConverterFactory(MoshiConverterFactory.create())
.build()
val frutasServices: Services = retrofit.create(Services::class.java)
My model:
package com.example.quitanda.models
import android.os.Parcelable
import com.squareup.moshi.Json
import kotlinx.parcelize.Parcelize
#Parcelize
data class ShoppingCart(
var count:Int=0,
#field:Json(name="product_title")
var name:String="",
#field:Json(name="product_id")
var id:Int=0,
#field:Json(name="photo_photo")
var photo:String="",
#field:Json(name="product_quant")
var quantidade:Int=0,
#field:Json(name="category_name")
var categoria:String="",
#field:Json(name="product_description")
var descricao:String="",
#field:Json(name="product_price_un")
var unidade:String="",
#field:Json(name="product_price_kg")
var kilo:String="",
var tipos:String=""): Parcelable
When I try to run my code it gives the following error
Does anyone have any idea how to fix this
who can help I am grateful
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.quitanda, PID: 11031
java.lang.RuntimeException: Cannot create an instance of class com.example.quitanda.models.FrutasViewModel
I wouldn't recommend doing what you're trying to achieve, because what Android did, is that they've abstracted how viewmodels are scoped, to give you developers the power to easily handle things like orientation-change.
In practice this means, that android views, such as Activity/Fragment implement a ViewModelStoreOwner which contains a ViewModelStore, which handles the scoping and retrieves the correct ViewModel instance based on context.
TL;DR: If you want an android arch.viewmodel then create it in your Activity/Fragment and pass it to the EntryAbstract, though chances are you just need some of the data, which could be set individually for better separation of concerns

flex inheritance class share

//Base.as
public class Base
{
private var _foo:String;
[Bindable]
public function set foo(value:String):void
{
_foo = value;
}
public function get foo():String
{
return _foo;
}
/*
Many many setter/getter, methods, events
*/
}
//Control.as
public class MyControl extends Group
{
public function MyControl()
{
}
}
//Window.as
public class MyWindow extends spark.components.Window
{
public function MyWindow()
{
}
}
//Module
public class MyModule extends spark.modules.Module
{
public function MyModule()
{
}
}
I want to expose (friendly) Base properties, methods and events on the other classes. Something like this:
var window:MyWindow = new MyWindow();
window.foo = 'Hello World!';
var module:MyModule = new MyModule();
module.foo = 'bar';
<namespace:MyControl foo="Hello World!"/>
I don't want define all the properties in each class because they are many and the same for all of them.
Ideally would define something like:
public class MyControl extends Group, Base
{
public function MyControl()
{
}
}
(I know it can't be done.)
Thanks!
UPDATE:
Thanks again!
Maybe this clarify more my need... On business layer I have a variable called processID (and businessID, operationID, localityID, etc.) what be passed to Window from Menu, and Window passes it to Module. On Module Container, I have a CustomComponent what query database using this variable as parameter. This applied for all (almost) Components on Module. These variables are defined as level business layer, then I define a Class to store and manage these variables (and some related methods operating with these variables using business logic), so I can make a standalone class (or library) for every environment to reusing my common components. The idea is... insert a new CustomComponent and set these variables via mxml, like this:
<custom:MyCustomComponent id="zzz" processID="{processID}" businessID="{businessID}"/>
Module has the business logic for set (o not) any of the variables.
Otherwise, I would have to implement different logic for the CustomComponent (and Module) for read parent's variables and define these variables only in MyWindow (using composite pattern).
You can get your answer from following link -
http://flexinonroids.wordpress.com/2009/05/27/flex-3-dynamically-loading-components-at-runtime/
http://thecomcor.blogspot.in/2007/11/adobe-flex-dynamically-loading-classes.html
Or you can follow below approach -
1) Create an Interface as base
2) Extend your class with interface
3) Load class at runtime with SWFLoader.loaderContext.applicationDomain.getDefinition method
Thanks,
Varun
You can place your classes that require friendly access in the same package as your Base class, and define private fields without any access modifier( it is equivalent to internal modifier).
Otherwise, you can define your namespace like that:
namespace my_internal;
and then define class members like that:
my_internal var _foo:String;
after that, those members will be hidden for all code, except for code that contains
use namespace my_internal;
You can read more here:
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f9e.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7f91
However, using 'friend access' can be an evidence of bad design, so if I were you I'd think twice before defining namespaces.
Update:
pseudo-superclass 1:
package proxy
{
public class Simple1
{
public var x:int;
public var y:int;
}
}
pseudo-superclass 2:
package proxy
{
import mx.controls.Alert;
public class Simple2
{
public var name:String = 'noname';
public function doAlert():void{
Alert.show(name);
}
//not normal method to replace 'this' with proxy
Simple2.prototype.doCrossClass = function doCrossClass():void{
Alert.show(''+(Number(this['x'])+Number(this['y'])));
}
}
}
Code for testing the result (looks as what you are expecting?):
var mega:Mega = new Mega();
mega.x = 100;
mega.y = 200;
mega.name = 'Multiple inheritance';
mega.doAlert();
mega.doCrossClass(); //300
And now pseudo-subclass with multiple inheritance:
package proxy
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public dynamic class Mega extends Proxy
{
public function Mega()
{
super();
}
public var superArray:Array = [new Simple1(), new Simple2()];
flash_proxy override function getProperty(name:*):*{
for each(var superClass:Object in superArray){
if( name in superClass){
return superClass[name];
}
}
throw new Error('no such property');
}
flash_proxy override function setProperty(name:*, value:*):void{
for each(var superClass:Object in superArray){
if( name in superClass){
superClass[name] = value;
return;
}
}
throw new Error('no such property');
}
flash_proxy override function callProperty(name:*, ...args):*{
for each(var superClass:Object in superArray){
if( name in superClass){
var f:Function = superClass[name] as Function;
return f.apply(this, args);
}
}
throw new Error('no such function');
}
}
}
You can also want to use javascript-like class construction(i.e. just using simple Object and assigning properties and functions to it in any combinations you want).

Swiz 1.3.1 LogProcessor

i try everything to get the LogProcessor for Swiz to run.
Here are the project Foomonger.
I fear however, the ressources refer to an old version of swiz.
I want to implement the LogProceccor without the SwizLoggerConfig, because i need only the possibility to log some informations to thunderbolt. i need no further configuration. After that i start to write my own AbstractSwizLoggingTarget.
If i copy the class into my environment, i get the follow error:
TypeError: Error #1034: Typumwandlung fehlgeschlagen: org.swizframework.utils.logging::SwizLogger#e8aa8b1 kann nicht in mx.logging.ILogger umgewandelt werden.
(Sorry for the german text)
Der Quelltext:
package de.axurit.util
{
import org.swizframework.core.Bean;
import org.swizframework.processors.BaseMetadataProcessor;
import org.swizframework.processors.ProcessorPriority;
import org.swizframework.reflection.IMetadataTag;
import org.swizframework.utils.logging.SwizLogger;
public class LoggerProcessor extends BaseMetadataProcessor
{
protected static const LOGGER:String = "Logger";
public function LoggerProcessor()
{
super([LOGGER]);
}
override public function get priority():int
{
return ProcessorPriority.INJECT +1;
}
override public function setUpMetadataTag(metadataTag:IMetadataTag, bean:Bean):void
{
var logger:SwizLogger = SwizLogger.getLogger(bean.source);
bean.source[metadataTag.host.name] = logger; //here occurs the error
}
override public function tearDownMetadataTag(metadataTag:IMetadataTag, bean:Bean):void
{
bean.source[metadataTag.host.name] = null;
}
}
}
Can anyone help me how to create an own MetadataProcessor for central logging (not debuggin) in Swiz. I you need more code, let me know that
Thank you
Frank
It was a long, hard journey. Here is teh result:
package de.axurit.util
{
import org.swizframework.core.Bean;
import org.swizframework.processors.BaseMetadataProcessor;
import org.swizframework.reflection.IMetadataTag;
import org.swizframework.utils.logging.SwizLogger;
public class LoggerProcessor extends BaseMetadataProcessor
{
public function LoggerProcessor()
{
super(["Log"]);
}
override public function setUpMetadataTag(metadataTag:IMetadataTag, bean:Bean):void
{
super.setUpMetadataTag(metadataTag, bean);
bean.source [metadataTag.host.name] = SwizLogger.getLogger(bean.source);
}
override public function tearDownMetadataTag(metadataTag:IMetadataTag, bean:Bean):void
{
super.tearDownMetadataTag(metadataTag,bean);
bean.source[metadataTag.host.name] = null;
}
}
}

Having a issue casting a object from an ArrayCollection to an instance of my Custom Class

I am using Flex 4 and for whatever reason I cannot get the following code to work which happens inside of a ListEvent handler for a dataGrid:
_tempRule = DataGrid(event.currentTarget).selectedItem as Rule;
Rule is a custom class, and the above code always returns null. The dataprovider for the datagrid is an ArrayCollection. If I try to wrap the above code to make it like the following:
DataGrid(event.currentTarget).selectedItem as Rule
I get this error:
TypeError: Error #1034: Type Coercion failed: cannot convert Object#e15a971 to com.mycompany.arcc.business.Rule
Now I know I have done this before with native Flex classes like Button, etc, but it my case it will not work.
Here is the Rule class:
package com.mycompaany.arcc.business
{
import flash.utils.describeType;
import mx.collections.ArrayCollection;
[Bindable]
public class Rule extends Object
{
public static const RANGE:String = "Range";
public static const SINGLE:String = "Single";
public static const LIST:String = "List";
/*name of the rule*/
private var _name:String;
/*rule group, like a radio group, only 1 rule from a group can be selected*/
private var _group:String;
/*Description of the group for the rule*/
private var _groupDescription:String;
/*Description of the rule*/
private var _description:String;
/*arry of values for this rule, based on the control type*/
private var _values:ArrayCollection;
/*min num of values*/
private var _numValues:int;
/*type of control to build, if range, 2 inputs, single, 1 , list 1 or more*/
private var _type:String;
public function Rule(name:String=null, group:String=null, description:String=null, values:ArrayCollection=null, numValues:int=0, type:String=null)
{
super();
_values = new ArrayCollection();
this._name = name
this._group = group;
this._description = description;
if (values)
{
this._values = values;
}
this._numValues = numValues;
this._type = type;
}
}
}
So what am I missing?
The quick and easy solution was to add the [RemoteClass] metatag at the top my custom class.
I found this solution on Adobe's website, livedocs.adobe.com/flex/3/html/…. It seems that using the native drag and drop capabilities between list-based components causes custom classes to lose their type during copying. Thanks to everyone for the assistance.
the errormessage is the result of an failed casting.
The better way is to use the cast like this,
Rule((event.currentTarget).selectedItem);
In this case, you will receive an exception, when the cast fails and not a null reference
BR
Frank

How to use SequenceRunner with FlexUnit 4

In the FlexUnit wiki I've read about the very interesting SequenceRunner that was contributed by the Fluint folks. Now I am trying to run a test that is very similar to the example, however when executing the run() Method of the SequenceRunner instance, I get this exception:
Cannot add asynchronous functionality to methods defined by Test,Before or After that are not marked async
Error: Cannot add asynchronous functionality to methods defined by Test,Before or After that are not marked async
at org.flexunit.async::AsyncLocator$/getCallableForTest()[C:\Users\dmoor e\Documents\_Production\Flex Unit 4\GIT\FlexUnit4\src\org\flexunit\async\AsyncLocator.as:82]
at org.fluint.sequence::SequenceWaiter/setupListeners()[C:\Users\dmoore\ Documents\_Production\Flex Unit 4\GIT\FlexUnit4\src\org\fluint\sequence\SequenceWaiter.as:100]
at org.fluint.sequence::SequenceRunner/continueSequence()[C:\Users\dmoor e\Documents\_Production\Flex Unit 4\GIT\FlexUnit4\src\org\fluint\sequence\SequenceRunner.as:177]
at org.fluint.sequence::SequenceRunner/run()[C:\Users\dmoore\Documents\_ Production\Flex Unit 4\GIT\FlexUnit4\src\org\fluint\sequence\SequenceRunner.as:124]
Has anyone used the SequenceRunner with FlexUnit 4 already. The [Test(async)] annotation is already present.
Here is a complete, very simple example test case class.
package test
{
import flash.events.Event;
import org.flexunit.asserts.assertEquals;
import org.fluint.sequence.SequenceRunner;
import org.fluint.sequence.SequenceWaiter;
public class test_case
{
[Test(async)]
public function test_function():void
{
var counter:Object = { count: 0}
var sr:SequenceRunner = new SequenceRunner(this);
sr.addStep(new SequenceWaiter(new TestWaiterTarget(counter), "myEvent", 50000));
sr.addStep(new SequenceWaiter(new TestWaiterTarget(counter), "myEvent", 5000))
sr.addAssertHandler(test_function_handler, counter);
sr.run();
}
private function test_function_handler(event:Event, passthroughData:*):void
{
assertEquals(passthroughData.count, 2);
}
}
}
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.utils.Timer;
class TestWaiterTarget extends EventDispatcher
{
var timer:Timer = new Timer(250, 1);
private var _counter:Object;
public function TestWaiterTarget(counter)
{
_counter = counter;
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timer_timerCompleteHandler);
timer.start();
}
private function timer_timerCompleteHandler(event:TimerEvent):void
{
_counter.count++;
dispatchEvent(new Event("myEvent"));
}
}
Thanks to Michael Labriola, who responded to my question in the Adobe Forum I was finally able to make it running. Note that the documentation of SequenceRunner in the Wiki is outdated and partially wrong.
Do not inherit from any TestCase class.
Skip the asyncHandler for CREATION_COMPLETE in the setUp. Rather add a SequenceWaiter in the test that waits for the CREATION_COMPLETE event of the component
The test must be marked as asynchronous test, so add the [Test(async)] Metadata to test cases that use SequenceRunner.

Resources