dev-resources.site
for different kinds of informations.
Safely restructure your codebase with Dependency Graphs
Published at
7/29/2024
Categories
typescript
dependency
graph
binding
Author
t_bi_a6d385ba2e05d3d128
Author
23 person written this
t_bi_a6d385ba2e05d3d128
open
Using "inversify" is a key to create Deoencency-Graph-Binding
import { Container } from "inversify";
var container = new Container();
export { container };
import { interfaces, namedConstraint, taggedConstraint, traverseAncerstors, typeConstraint } from "inversify";
class BindingHelper
{
targetNamed(request: interfaces.Request, name: string | number | symbol): boolean
{
return request != null && request.target.matchesNamedTag(name.toString());
}
targetTagged(request: interfaces.Request, key: string | number | symbol, value: unknown): boolean
{
return request != null && request.target.matchesTag(key)(value);
}
targetIsDefault(request: interfaces.Request): boolean
{
return request != null && request.target != null && !request.target.isNamed() && !request.target.isTagged();
}
injectInto(request: interfaces.Request, parent: (NewableFunction | string)): boolean
{
return request != null && typeConstraint(parent)(request.parentRequest);
}
parentNamed(request: interfaces.Request, name: string | number | symbol): boolean
{
return request != null && namedConstraint(parent)(request.parentRequest);
}
parentTagged(request: interfaces.Request, tag: string | number | symbol, value: unknown): boolean
{
return request != null && taggedConstraint(tag)(value)(request.parentRequest);
}
anyAncestorIs(request: interfaces.Request, ancestor: (NewableFunction | string)): boolean
{
return traverseAncerstors(request, typeConstraint(ancestor));
}
noAncestorIs(request: interfaces.Request, ancestor: (NewableFunction | string)): boolean
{
return !traverseAncerstors(request, typeConstraint(ancestor));
}
anyAncestorTagged(request: interfaces.Request, tag: string | number | symbol, value: unknown): boolean
{
return traverseAncerstors(request, taggedConstraint(tag)(value));
}
noAncestorTagged(request: interfaces.Request, tag: string | number | symbol, value: unknown): boolean
{
return !traverseAncerstors(request, taggedConstraint(tag)(value));
}
anyAncestorNamed(request: interfaces.Request, name: string | number | symbol): boolean
{
return traverseAncerstors(request, namedConstraint(name));
}
noAncestorNamed(request: interfaces.Request, name: string | number | symbol): boolean
{
return !traverseAncerstors(request, namedConstraint(name));
}
}
var when = new BindingHelper();
export { when };
import { Container, interfaces } from "inversify";
import { when } from "./context-binding-helper";
interface DependencyBranch
{
from(type: any): DependencyGraphHelper;
}
class DependencyGraphHelper implements DependencyBranch
{
private container: Container;
private graphs: any[] = [];
private isBranching: boolean;
private branchNode: any;
bind(identifier: any, type: any, isConstant: boolean = false): DependencyGraphHelper
{
if (this.isBranching)
{
console.error('Please specify which class to be branched from. Parameters: ', identifier, ' ', type);
}
var parent = this.graphs[this.graphs.length - 1];
var node = { identifier: identifier, type: type, parent: parent, isConstant: isConstant };
this.graphs.push(node);
return this;
}
branch(identifier: any, type: any, isConstant: boolean = false): DependencyBranch
{
if (this.graphs.length == 0)
{
console.error('Dependency graph cannot start with a "branch". It must start with a "bind" function.Parameters: ', identifier, ' ', type);
}
if (this.isBranching)
{
console.error('Please specify which class to be branched from. Parameters: ', identifier, ' ', type);
}
this.isBranching = true;
this.branchNode = { identifier: identifier, type: type, isConstant: isConstant };
return this;
}
from(type: any): DependencyGraphHelper
{
if (this.isBranching == false)
{
console.error('A "from" function must be called after a "branch" function. Parameters: ', type);
}
this.isBranching = false;
var parent = this.graphs.filter(i => i.type == type).pop();
this.branchNode.parent = parent;
this.graphs.push(this.branchNode);
return this;
}
registerTo(container: Container): void
{
if (this.isBranching)
{
console.error('Please specify which class to be branched from before call "register" function.');
}
this.container = container;
for (let index = 0; index < this.graphs.length; index++)
{
const graph = this.graphs[index];
this.registerGraph(graph);
}
this.graphs = [];
this.container = null;
}
private registerGraph(graph: any): void
{
if (graph.isConstant)
{
this.bindToConstant(graph);
}
else
{
this.bindTo(graph);
}
}
private bindTo(graph: any): void
{
this.container.bind(graph.identifier).to(graph.type).when(request =>
{
return this.recursiveCheckBindingCondition(request, graph);
});
}
private bindToConstant(graph: any): void
{
this.container.bind(graph.identifier).toConstantValue(graph.type).when(request =>
{
return this.recursiveCheckBindingCondition(request, graph);
});
}
private recursiveCheckBindingCondition(request: interfaces.Request, graph: any): boolean
{
if (graph.parent == null)
{
return true;
}
var injected = when.injectInto(request, graph.parent.type) && this.recursiveCheckBindingCondition(request.parentRequest, graph.parent);
return injected;
}
}
var dependencyGraph = new DependencyGraphHelper();
export { dependencyGraph };
import { dependencyGraph } from "../../common/ioc-helper/dependency-graph-helper";
import { container } from "../../ioc/ioc-container";
import { MonkeyClimb } from "../monkey/monkey-climb";
import { MonkeyControl } from "../monkey/monkey-control";
import { MonkeyEat } from "../monkey/monkey-eat";
import { MonkeyFindFood } from "../monkey/monkey-find-food";
import { MonkeySwingThroughTheTree } from "../monkey/monkey-swing-through-the-tree";
import { MONKEY } from "./animal-ioc-config";
export default class DependenceGraphBinding
{
public register(): void
{
this.registerMonkey();
}
private registerMonkey(): void
{
dependencyGraph
.bind(MONKEY.CONTROL,MonkeyControl)
.branch(MONKEY.EAT,MonkeyEat).from(MonkeyControl)
.branch(MONKEY.FIND_FOOD,MonkeyFindFood).from(MonkeyControl)
.branch(MONKEY.FIND_FOOD,MonkeyClimb).from(MonkeyFindFood)
.branch(MONKEY.FIND_FOOD,MonkeySwingThroughTheTree).from(MonkeyFindFood)
.registerTo(container);
}
}
binding Article's
20 articles in total
Safely unwrap optional values in SwiftUI bindings
read article
Safely restructure your codebase with Dependency Graphs
currently reading
Data not updated?WPF
read article
What is Property binding and how to implement it in Angular?
read article
This is awkward in JavaScript
read article
How to Bind to a DataTemplate in UWP
read article
JavaScript functional binding(thisExplained)
read article
Six ways to use data binding with Vue.js
read article
Binding a service to a micro-service using odo
read article
Develop a TextField validator for SwiftUI (Episode 2)
read article
Settling the editors key bindings war
read article
Vue two way data-binding in custom checkbox
read article
React Simple Data Binding example
read article
Angular Learning Day 3: Displaying Data and Handling Events
read article
Auto binding Input() and Output() in Angular9+
read article
VUE v-model, two-way data binding and editing in multi nested components, dynamic components
read article
Angular Done Right: Part 1 — Binding and Directives
read article
Using PatchValue on FormArrays in Angular 7
read article
Binding in React
read article
React Tips: 2 - Binding an Event Handler
read article
Featured ones: