MarimerLLC / cslajs

CSLA for JavaScript
Other
12 stars 8 forks source link

Implement metastate and property management #9

Closed JasonBock closed 9 years ago

JasonBock commented 10 years ago

We need a way to track when properties change so we'll know when to fire rules and change metastate on a BO (e.g. isSavable, isDirty, isNew, etc.)

One whiteboard approach:

public class Stuff : BusinessBase { public get x(): int { return this.getProperty("x"); }

public set x(val: int) { this.setProperty("x", val); } }

Where getP/setP would be defined on the base class. Unfortunately all TS/JS supports is the notion of public and private, so these methods would have to be public for the subclass to call them.

It may be possible to take advantage of JS's dynamic nature to only add properties to a private collection if the developer has called the getP/setP. This would allow the dev to not have to define a private backing field and let CSLA handle that. A problem may be if the property doesn't have a defined backing field yet, so what would "return this.getProperty("x");" do for an int? Even with generics in TypeScript we probably won't have enough information at runtime to synthesize the property correctly. So we may end up with this:

public class Stuff : BusinessBase { private _x: int;

public get x(): int { return this.getProperty("x", "_x"); }

public set x(val: int) { this.setProperty("x", "_x", val); } }

For this issue, only define the metastate properties and change them with setProperty(). Rules (business + authorization) will be addressed later (so no broken rules collection as of yet).

mikemccaughan commented 10 years ago

I'll jump on this one.

mikemccaughan commented 9 years ago

I need to learn Git, specifically branching and pull requests. I've got a solution based on Object.keys that looks like this:

    // Object.keys gets all members of a class; this gets just the properties.
    var props = Object.keys(this).map(function (key: string) {
      if (typeof this[key] !== "function") {
        return key;
      }
    });
    props.forEach(function (prop: string): void {
      // Right now, I'm using the convention that two underscores are used to denote 
      // metadata-carrying property names.
      if (prop.substring(0, 2) === "__") {
        this[prop] = prop.substring(2);
      }
    });

Consumers have to add fields to their objects which match the name of their properties with the __ prefix, typed as a string, like this:

class Child extends Csla.Core.BusinessBase {
  private __childProp: string;

  public create(parameters?: any): void {
    this.isLoading = true;
    this.childProp = parameters;
    this.isLoading = false;
  }

  public get childProp(): number {
    return this.getProperty(this.__childProp);
  }
  public set childProp(value: number) {
    this.setProperty(this.__childProp, value);
  }
}