i am sorry to say so, but what you want to do, is simply impossible
... it is not so much about package-level introspection ... if there were a way, it still would not be possible ...
the actual problem is:
all ActionScript compilers always only compile the main class and dependancies ... thus, if your Rule implementations never are mentioned anywhere, they will not be compiled into the resulting swf ... in consequence, they will not be available at runtime at all ...
the closest thing to what you want to do, would probably be to write a build script, that traverses your packages, and - following some rule - registers the classes using some automatically generated code ... the least you need, is an Array literal, containing all the classes
[Rule1, Rule2,...RuleN]
as simple as that ... relying on the fact that all rules are in the same package (which i find an awful restriction), you could then use getDefinitionByName
to get the right class ...
IMHO however, apart from not being easy to accomplish, the approach is also bad style ... it's quite hackish, and imposes way too much ...
the map approach is pretty much the best you can get ... by using the map, the classes appear in you code and are thus compiled, and it's a clean way for a lookup ... also, you have more influence ...
you could create rules like this:
class NameIsRule implements IRule {
private var _name:String;
public function NameIsRule(name:String) {
this._name = name;
}
public function applyTo(target:Object):* {
return target.hasOwnProperty("name") && (target.name == this._name)
}
}
and then have
rules = {
isCalledJim : new NameIsRule("Jim"),
isCalledJohn : new NameIsRule("John")
}
(stupid example, but i hope it illustrates the point)
and you might wanna wrap that into a class, to be cleaner ...
package {
public class RuleMap {
private var _rules:Object = {}
public function RuleMap(init:Object = null) {
for (var name:String in init)
this.addRule(name, init[name]);
}
public function addRule(id:String, rule:IRule):IRule {
if (this.ruleExists(id))
throw new Error("duplicate rule for id " + id);
if (rule == nul)
throw new ArgumentError("invalid value null for parameter rule");
this._rules[id] = rule;
return rule;
}
public function applyRule(id:String, target:Object):* {
return this.getRule(id).applyTo(target);
}
public function getRule(id:String):IRule {
if (this.ruleExists(id))
return this._rules[id];
else
throw new Error("no rule for id " + id);
}
public function ruleExists(id:String):Boolean {
return this._rules.hasOwnProperty(id);
}
}
}
this is a little more verbous (well, you can always pass in an object to the constructor), but it is much safer, throws more reasonable values, and is faster, since AVM2 is faster when executing strictly typed code (in contrast to dynamic code, you actually make use of the interface ... it is quite pointless to declare an interface, if none of your code relies on it) ...
also, you should take the time, to create constants for the rules, instead of having tons of string literals all over you code ... this will help against typos etc. ...
when working with sealed classes in AS3, as you do, untyped coding does not offer any benefits, because it makes only real sense with ducktyped languages ... and AS3 is not ... in strict languages, keep strict, and the compiler will do a lot of work for you, and save you a lot of debugging time ...
i like the idea behind the Rules (nice, clean and flexible), but IMHO, you should rather be more exact than lazy at that Point ... i'd guess, this is something rather at the heart of your App ... so let it be rock solid ... ;)