我在项目之间有一些免费的日子,所以我决定学习typescript
。
因此我想做一个存储库工厂。这个想法很简单,有一些API
我可以访问models
crud行为。对于buisnes模型,有一个generic
repository
是很好的解决方案。但仍然从model
方法中获取CRUD
类。
这样做的正确方法是什么?有人可以帮我解决这个问题吗?怎么做对了?
我想要的是:
var factory = new RepositoryFactory($resource, 'http://api.com');
var repo = factory.getRepository(User);
var user = repo.getAll();
我很想做这样的事:
IEntity
:
'use strict';
export interface IEntity {
id: number;
}
IRepository
:
'use strict';
import {IEntity} from "./IEntity";
export interface IRepository<T extends IEntity> {
getAll(params:Object): T[];
getById(id:number): T;
create(data:Object): T;
update(id:number, data:{id:number}): T;
remove(id:number): boolean;
}
RepositoryFactory
'use strict';
import {IEntity} from "./IEntity";
import {Repository} from "./Repository";
export default class RepositoryFactory {
protected $resource:any;
protected url:string;
constructor($resource:any, url:string) {
this.$resource = $resource;
this.url = url;
}
public getRepository<T extends IEntity>(model:T):Repository {
return new Repository(this.$resource, this.url, model)
}
}
`Repository`:
'use strict';
import {IRepository} from "./IRepository";
import {IEntity} from "./IEntity";
export default class Repository<T extends IEntity> implements IRepository<T> {
protected $resource:any;
protected resource:any;
protected url:string;
protected model:T;
constructor($resource:any, url:string, model:T) {
this.$resource = $resource;
this.url = url;
this.model = model;
this.resource = this.getResource(model.path);
}
getAll(params:Object):T[] {
let results = this.resource.query((typeof params === 'undefined' ? {} : params), this.onSuccess);
return this.returnPromise(results);
}
getById(id:number):T {
let model = this.resource.get({id: id}, this.onSuccess);
return this.returnPromise(model);
}
create(data:Object):T {
let model = new this.resource(data);
return model.$save().then(this.onSuccess);
}
update(id:number, data:Object):T {
data.id = id;
var model = new this.resource(data);
return model.$update().then(this.onSuccess);
}
remove(id:number):boolean {
var data = {id: id};
var model = new this.resource(data);
return model.$delete().then(this.onSuccess);
}
protected getResource(path:string) {
return this.$resource(this.url + path, {id: '@id'}, {
'update': {
method: 'PUT'
},
'get': {
method: 'GET'
},
'save': {
method: 'POST'
},
'query': {
method: 'GET'
},
'remove': {
method: 'DELETE'
},
'delete': {
method: 'DELETE'
}
});
}
protected onSuccess(response:any) {
if (this.checkPropertyExistence(response, 'data')) {
if (response.data instanceof Array) {
let results = response.data;
for (var key in results) {
if (results.hasOwnProperty(key)) {
results[key] = new this.model(results[key]);
}
}
return results;
} else {
return new this.model(response.data);
}
}
return response;
}
protected transformRequest(obj:Object) {
var str = [];
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
}
return str.join("&");
}
protected returnPromise(object:Object) {
return object.$promise.then(function (result) {
return result;
});
}
protected checkPropertyExistence(obj:Object, paths:string|string[]) {
for (var i = 0; i < paths.length; i++) {
if (!obj || !obj.hasOwnProperty(paths[i])) {
return false;
}
obj = obj[paths[i]];
}
return true;
}
}
User
:
'use strict';
import {IEntity} from "./IEntity";
export default class User implements IEntity {
id:number;
name:string;
static _path:string = '/users';
constructor(id:number, name:string) {
this.id = id;
this.name = name;
}
static get path():string {
return this._path;
}
}
答案 0 :(得分:2)
嘿伙计们,我有人为你创造工作榜样。
该示例显示了如何使用typescript
创建存储库工厂。
我准备了这个DEMO FIDDLE,您可以在右侧按RUN
,然后会出现带有单个按钮的页面。点击console.log
按钮后,系统会显示getAll
方法results
。
在示例中,我模拟了数据,只是为了表明工厂的工作原理。如果有人想改进它,请随意欢迎这样做!
它是如何工作的?
//create factory, you can do it in an abstract controller class
//and later extends controller by it so you can easy get access to repository
var factory = new RepositoryFactory();
//inject path for $resource (unused in example)
//and your model.entity namespace
var repo = factory.getRepository('/users', 'User');
//call repo method
var users = repo.getAll({});
使用角度创建RepositoryFactory
作为service
时。就这样。您可能还需要注入$resource
以从API
获取正确的数据。
这是一个完整的示例代码:
interface IEntity {
id: number;
}
class Entity implements IEntity {
private _id:number;
private _name:string;
private _birth:Date;
constructor(parameters: {id:number, name:string, birth:Date}) {
this._id = parameters.id;
this._name = parameters.name;
this._birth = parameters.birth;
}
get id():number {
return this._id;
}
set id(value:number) {
this._id = value;
}
get name():string {
return this._name;
}
set name(value:string) {
this._name = value;
}
get birth():Date {
return this._birth;
}
set birth(value:Date) {
this._birth = value;
}
}
class RepositoryFactory {
public getRepository<T extends IEntity>(path:string, model:string):IRepository<T> {
return new Repository<T>(path, model)
}
}
interface IRepository<T extends IEntity> {
getAll(params:Object): T[];
getById(id:number): T;
create(data:Object): T;
update(id:number, data:{id:number}): T;
remove(id:number): boolean;
}
class Repository<T extends IEntity> implements IRepository<T> {
protected path:string;
protected model:string;
constructor(path:string, model:string) {
this.path = path;
this.model = model;
}
getAll(params:Object):T[] {
let results = [
{id:1, name: 'rafal', birth:new Date()},
{id:2, name: 'szymon', birth:new Date()},
{id:3, name: 'mateusz', birth:new Date()},
];
let entities= [];
for (var key in results) {
if (results.hasOwnProperty(key)) {
let entity = Object.create(window[this.model].prototype);
entity.constructor.apply(entity, new Array(results[key]));
entities.push(entity);
}
}
return entities;
}
getById(id:number):T {
let object = {id:id, name: 'test', birth:new Date()};
var entity = Object.create(window[this.model].prototype);
entity.constructor.apply(entity, new Array(object));
return entity;
}
create(data:Object):T {
var entity = Object.create(window[this.model].prototype);
entity.constructor.apply(entity, new Array(data));
return entity;
}
update(id:number, data:Object):T {
var entity = Object.create(window[this.model].prototype);
entity.constructor.apply(entity, new Array(data));
return entity;
}
remove(id:number):boolean {
return true;
}
}
var factory = new RepositoryFactory();
var repo = factory.getRepository('/users', 'Entity');
var users = repo.getAll({});