Understanding and Assigning String values in AS3 - string

I am kinda new to AS3, and I want to figure out how classes and strings work. I have two files:
Main.as:
package
{
import flash.display.*;
public class Main extends Sprite
{
public function Main():void
{
var f1:Flower = new Flower("rose");
var f2:Flower = new Flower("cactus");
var f3:Flower = new Flower("fff");
}
}
}
Flower.as:
package
{
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Flower
{
protected var name:String;
public function Flower(name:String):void
{
setName(name);
var updateTimer:Timer;
updateTimer = new Timer(500.6, 2);
updateTimer.addEventListener(TimerEvent.TIMER, TimerFun);
updateTimer.start();
}
public function TimerFun(e:TimerEvent):void
{
trace ("test " + getName());
setName("xxx");
}
public function setName(name:String):void
{
this.name = name;
}
public function getName():String
{
return name;
}
}
}
So basically from what I understand, every time I create an instance to the class "Flower.as" like this:
var f1:Flower = New Flower("rose"));
it saves each instance to a new line in the protected var name which is located at flower.as. then I can get the names with getnames. I placed a timer to check the values, and inside the timer I decided to try to assign a new name with the function setName("xxx"), and I set the timer to activate itself twice in order to see how the results change; However, all it did was replace all of the instances with the value "xxx", it didn't add anything(I expected a new string named "xxx" along with the others). I need an explanation about what
var f1 Flower:Flower = New Flower("rose");
does exactly and what setName("xxx") does. Thank you for your time.

Okey let me try to explain it for you :)
When u creat this : var f1:Flower; = new Flower("rose"); u creat a flower and give it name as "rose". But however when u creat a Flower type variable it trigger a TimerEvent. When TimerEvent start working first line will give to you
"test rose" on your output panel. But the second line is using setName("xxx") function for changing Flower's name.
So when u look your output panel u should see something like this :
test rose
test xxx
I hope this will enough to understand. If u have a question just ask :)

Related

Conflicts in AutoMapper and AutoFixture

I have 2 classes, Class1 should be mapped to Class2. I do mapping with AutoMapper. I'd like to test my configuration of the mapper and for this purposes I'm using AutoFixture. Source class Class1 has property of type IList<>, destination class Class2 has a similar property but of type IEnumerable<>. To simplify test preparation I'm using AutoFixture (with AutoMoqCustomization) to initialize both source and destination objects. But after initializing property of type IEnumerable<> with AutoFixture, AutoMapper can't map the property.
Error text:
Error mapping types.
Mapping types: Class1 -> Class2 ConsoleApplication1.Class1 ->
ConsoleApplication1.Class2
Type Map configuration: Class1 -> Class2 ConsoleApplication1.Class1 ->
ConsoleApplication1.Class2
Property: Items
Could anybody help me to configure either AutoMapper or AutoFixture to make the mapping work? As a workaround I can assign null to the destination property, but I do not want to do this in the each test.
Simplified example of code:
public class AutoMapperTests
{
public static void TestCollectionsProperty()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ItemClass1, ItemClass2>();
cfg.CreateMap<Class1, Class2>();
});
var src = new Class1();
src.Items = new List<ItemClass1>()
{
new ItemClass1() { Text = "111" },
new ItemClass1() { Text = "222" }
};
var fixture = new Fixture();
var dst = fixture.Create<Class2>();
Mapper.Map(src, dst); //Error at this line of code
}
}
public class Class1
{
public IList<ItemClass1> Items { get; set; }
}
public class Class2
{
public IEnumerable<ItemClass2> Items { get; set; }
}
public class ItemClass1
{
public string Text { get; set; }
}
public class ItemClass2
{
public string Text { get; set; }
}
It's not really an AutoFixture issue per se. You can reproduce it without AutoFixture by instead creating dst like this:
var dst = new Class2();
dst.Items = Enumerable.Range(0, 1).Select(_ => new ItemClass2());
This will produce a similar error message:
Unable to cast object of type 'WhereSelectEnumerableIterator2[System.Int32,Ploeh.StackOverflow.Q45437098.ItemClass2]' to type 'System.Collections.Generic.IList1[Ploeh.StackOverflow.Q45437098.ItemClass2]'
That ought to be fairly self-explanatory: WhereSelectEnumerableIterator<int, ItemClass2> doesn't implement IList<ItemClass2>. AutoMapper attempts to make that cast, and fails.
The simplest fix is probably to avoid populating dst:
var dst = new Class2();
If you must use AutoFixture for this, you can do it like this:
var dst = fixture.Build<Class2>().OmitAutoProperties().Create();
Unless the Class2 constructor does something complex, however, I don't see the point of using AutoFixture in that scenario.
If, on the other hand, you do need dst to be populated, you just need to ensure that dst.Items is convertible to IList<ItemClass2>. One way to do that would be like this:
var dst = fixture.Create<Class2>();
dst.Items = dst.Items.ToList();
You could create a Customization to make sure that this happens automatically, but if you need help with that, please ask a new question (if you don't find one that already answers that question).
Here is a working example for your problem. As #Mark Seemann already told, Mapper.CreateMap has been deprecated, so this example is using the new structure.
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ItemClass1, ItemClass2>();
cfg.CreateMap<Class1, Class2>();
});
var src = new Class1();
src.Items = new List<ItemClass1>()
{
new ItemClass1() { Text = "111" },
new ItemClass1() { Text = "222" }
};
var dest = Mapper.Map<Class1, Class2>(src);
AM requires IList because you're mapping to an existing list and that works by calling IList.Add.

How to override "="

I was looking into Haxe abstracts and was very interested in building an abstract that would wrap a class and unify it to, in my case, an Int.
#:forward()
abstract Abs(Op)
{
public inline function new(value:Int = 0, name:String = "unnamed" )
{
this = new Op();
this.value = value;
this.name = name;
}
#:to
private inline function toInt():Int
{
return this.value;
}
}
class Op
{
public var value:Int = 0;
public var name:String = "no name";
public function new()
{
}
}
The problem I ran in to is when defining a #:from method - it has to be static and can take only one parameter - a new value. So whenever I set the abstract's instance value from the #:from method I will have to create a new instance of the abstract, thus resetting all the variables.
Basically what I'm talking about is this:
var a = new Abs(5, "my abs"); // value is 5; name is "my abs"
a = 100; // value is 100; name is reset to "unnamed" but I want it to be preserved
As much as I could find out we cannot overload the = operator in abstracts other than through implicit casting with a #:from method and I haven't found a way to really achieve this with macros.
If you have any ideas on how this can be done, please provide a minimalist example.
It depends what you want to do, but if you use this:
var a = new Abs(5, "my abs");
var myInt:Int = a;
It will use the abstract Abs.toInt function.
#:to
private inline function toInt():Int
{
return this.value;
}
The other way around also works:
var million = 1000000;
var myAbs:Abs = million;
It will use the static Abs.fromInt function.
#:from
static inline function fromInt(value:Int)
{
return new Abs(value, "what");
}
This is because it uses the implicit cast. http://haxe.org/manual/types-abstract-implicit-casts.html
Try it yourself: http://try.haxe.org/#Ae1a8
Is that what you are looking for?

as3 worker with 1009 TypeError for unknown reason

I'm working on a AS3 script where I try to start a thread. I keep getting the 1009 error below when I try. I'm following a howto page from the internet pretty closely. I'm using (I think) version 11.4 of flash.
TypeError: Error #1009: Cannot access a property or method of a null
object reference.
This refers to the line where swfBytes is assigned this.loaderInfo.bytes.
package somepackage {
import flash.system.MessageChannel;
import flash.system.Worker;
import flash.system.WorkerDomain;
import flash.events.Event;
import flash.utils.ByteArray;
public class SomeClass extends Sprite{
public var mainToWorker:MessageChannel;
public var workerToMain:MessageChannel;
public var worker:Worker;
public function SomeClass() {
// constructor code
if (Worker.current.isPrimordial) {
var swfBytes:ByteArray = this.loaderInfo.bytes;// HERE
worker = WorkerDomain.current.createWorker( swfBytes );
mainToWorker = Worker.current.createMessageChannel(worker);
workerToMain = worker.createMessageChannel(Worker.current);
worker.setSharedProperty("mainToWorker", mainToWorker);
worker.setSharedProperty("workerToMain", workerToMain);
//workerToMain.addEventListener(Event.CHANNEL_MESSAGE, onWorkerToMain);
//worker.start();
}
else {
mainToWorker = Worker.current.getSharedProperty("mainToWorker");
workerToMain = Worker.current.getSharedProperty("workerToMain");
//mainToWorker.addEventListener("mainToWorker", onMainToWorker);
}
}
}
}
If anyone has seen this before or knows what I'm doing wrong I'd be most appreciative.
I'm instantiating this as part of a much larger group of classes. I thought that might be my problem, so I instantiated this class on it's own at the 'actions' script page of the root scene. I'm using Flash CS6. There is not much on the 'actions' page I was referring to.
var ai:SomeClass = new SomeClass();
addChild(ai);
EDIT 1:
Here I've included a 'addEventListener' line. This code seems to work in debug mode but not if I just play the movie regularly. If I play it regularly I get the 1009 error again, presumably for the line after the trace. What could I replace 'Event.ADDED_TO_STAGE' with that would allow this to run??
package somepackage {
public class SomeClass extends Sprite{
public var mainToWorker:MessageChannel;
public var workerToMain:MessageChannel;
public var worker:Worker;
public function SomeClass() {
if (Worker.current.isPrimordial) {
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
}
public function onAddedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
trace(this.loaderInfo);
var swfBytes:ByteArray = this.loaderInfo.bytes;
worker = WorkerDomain.current.createWorker( swfBytes );
mainToWorker = Worker.current.createMessageChannel(worker);
workerToMain = worker.createMessageChannel(Worker.current);
worker.setSharedProperty("mainToWorker", mainToWorker);
worker.setSharedProperty("workerToMain", workerToMain);
workerToMain.addEventListener(Event.CHANNEL_MESSAGE, onWorkerToMain);
worker.start();
}
}
}

AS3 - target variable using another variable string value

okay. so i have a function and i've passed a parameter through it called objectName.
no i have no idea how to do this or explain it. so here goes.
public function moveObject(ObjectName):void{
//objectName now holds "myName" which is an object also
//i would now like my variable called myNamePosition to equal 10
//so it would need to grab the value of objectName which is myName:Object.
//turn it into a string of some kind - myName:string
//add "Position" to the end of it so its myNamePosition
// make it equal to 10
trace(myNamePosition);
}
The functions parameters passed through would change so i cant actually use "myName". but rather "objectName".
Thanks
Example:
package
{
import flash.display.MovieClip;
public class astest extends MovieClip
{
public function astest()
{
init();
}
private var myNamePosition:int;
private function init():void
{
moveObject({myName:{}})
}
public function moveObject(objectName:Object):void
{
var propName:String;
for(propName in objectName)
break;
trace(propName);
propName+="Position";
trace(propName);
this[propName] = 10;
var propValue:* = this[propName];
trace(propValue);
}
}
}
output:
myName
myNamePosition
10
Is it what you need?

Subsonic 3, how to CRUD using LinqTemplates?

I am new to Subsonic, and it seems that I cant find out a natural way to do CRUD operations using the LINQ template classes. I guess in ActiveRecord, you could:
Product p = new Product();
p.ProductCode = "xxx";
p.Add();
Using the LINQTemplate generated classes however, how can I do the same thing? I can only use something like this below to insert a product object:
db.Insert.Into<UnleashedSaaS.PRODUCT>(prod => prod.Code, prod => prod.Description).Values("Product1", "Product1 Desc").Execute();
Who could kindly give me some hints? I'd really appreciate it.
All the CRUD happens in SubSonicRepository, which you can derive from. For example, I would have a class like this:
public class ProductRepository : SubSonicRepository<Product> {
public ProductRepository() : base(new NorthwindDB()) { }
// need this here because base doesn't expose the DB class that I know of
protected NorthwindDB _db;
protected NorthwindDB DB {
get {
if (_db == null) _db = new NorthwindDB();
return _db;
}
}
public void Save(Product product) {
if (product.ProductId == 0) {
Add(product); // Add is part of SubSonicRepository
} else {
Update(product);
}
}
public void Delete(Product product) { ... }
public List<Product> ListAll() {
var products = from p in DB.Products
select p;
return products.ToList();
}
public Product GetById(int id) {
return DB.GetByKey(id);
}
}
And so on. It's nice because you can consolidate all your data access methods in one place. If you have Sprocs, they're generated as methods on DB as well.
When I get time I'm going to work on adding a Save method to SubSonicRepository directly so you don't have to do the check yourself to see which method (Add or Update) to call.
I have modified the Classes.tt file to include:
public partial class <#=tbl.ClassName#>Repository : SubSonicRepository<<#=tbl.ClassName#>>
{
public <#=tbl.ClassName#>Repository() : base(new <#=DatabaseName#>DB()) { }
}
Insert that bunch of lines between
<# foreach(Table tbl in tables){#>
and
/// <summary>
right at the top, near the namespace declaration, in my file it can be inserted in line 18.
The last thing to do is to add another "using" statement, in line 10, the next line after System.Linq statement. Now it should look like:
using System.Linq;
using SubSonic.Repository;
That will generate a repository to give you access to basic functionality, but can be modified in another partial class.
Hope that helps.

Resources