아직도 미련을 못버렸네..
DIContainer.ts
export interface IDIContainer {
regist: <T extends unknown>(name: string, builder: T | (() => T)) => void;
resolve: <T extends unknown>(name: string) => T;
}
class DIContainer implements IDIContainer {
private instances: Record<string, any> = {};
regist = <T extends unknown>(
name: string,
instanceBuilder: T | (() => T)
): void => {
this.instances[name] = instanceBuilder;
};
resolve = <T extends unknown>(name: string): T => {
const instance = this.instances[name];
if (!instance) throw new Error(`regist ${name} first`);
if (typeof instance === "function") {
const builder = instance as () => T;
this.instances[name] = builder();
}
return this.instances[name] as T;
};
}
const globalContainer: IDIContainer = new DIContainer();
export const getDIContainer = () => globalContainer;
DIContext.tsx
const DiContext = createContext<IDIContainer | null>(null);
export const DiProvider: FC<PropsWithChildren> = ({ children }) => {
const container = useRef(getDIContainer());
return (
<DiContext.Provider value={container.current}>
{children}
</DiContext.Provider>
);
};
export const useDiContainer = () => {
return useContext(DiContext)!;
};
export const useDIContainerInstance = <T extends unknown>(name: string): T => {
const container = useContext(DiContext)!;
const instance = useRef<T>(container.resolve<T>(name));
return instance.current;
};