InversifyJS: Injecting the class which extends non-injectable external module - inversifyjs

Need help on implementation related to Inversify. I am creating a class which is extending EventEmitter from node. when I try to use inversify it says EventEmitter is not injectable. Following is the sample code
//Interface
export interface ISubscriber {
Connect(callback: Function);
on(event: string, listener: Function): this;
emit(event: string, ...args: any[]): boolean;
}
//Class
import {EventEmitter} from 'events';
#injectable()
class Subscriber extends EventEmitter implements ISubscriber {
logProvider: SCLogging.ILogger;
public constructor(
#inject(TYPES.ILogger) logProvider: SCLogging.ILogger,
#inject(TYPES.IConfig) config: IConfig
) {
super();
//Some Implementation
}
public Connect(callback) {
//Some Implementation
}
public on(event: string, listener: Function): this {
super.on(event, listener);
return this;
}
public emit(event: string, ...args: any[]): boolean {
return super.emit(event, ...args);
}
}
export { ISubscriber, Subscriber }
//Define Binding
kernel.bind<SCLogging.ILogger>(TYPES.ILogger).to(Logger);
kernel.bind<IConfig>(TYPES.IConfig).to(Config);
kernel.bind<ISubscriber>(TYPES.ISubscriber).to(Subscriber);
I get error
Error: Missing required #injectable annotation in: EventEmitter.

a very similar question has been already answered on the InversifyJS issues on Github:
You can invoke the decorator using the decorate function:
import { decorate, injectable } from "inversify";
decorate(injectable(), ClassName)
Check out https://github.com/inversify/InversifyJS/blob/master/wiki/basic_js_example.md for more info.
Please refer to the issue on Github for more information.

Setting skipBaseClassChecks: true in the container options disables this "feature" of inversify.
See this PR for more details https://github.com/inversify/InversifyJS/pull/841

Related

Inject service or class in guard in NestJS

Needs to DI Kafka client in guard:
auth.guard.ts
export class AuthGuard implements CanActivate {
private _client: ClientKafka; <----- // TODO implement nestjs DI mechanism
public async canActivate(context: ExecutionContext): Promise<boolean> {
try {
const request = context.switchToHttp().getRequest();
const authorization: string = request.get('Authorization');
...code here just send data to jwt service...
return true;
} catch (err) {
return false;
}
}
}
I use new in canActivate for creating an instance of Kafka client in auth.guard.ts. But how to inject a class in guard with #Inject? I used to create #Global module, which provides and export Kafka client class, but it's not working...
Use This in the module for globally using the guard
providers: [{provide: APP_GUARD, useClass: AuthGuard}]
As for your question about injecting a class inside a guard, you need to inject it inside the constructor of the AuthGuard class
export class AuthGuard implements CanActivate {
constructor(private clientKafka : ClientKafka){}
}
if this doesn't work, try using
constructor(#Inject(private clientKafka : ClientKafka)){}
Hope this resolves your issue :)

Dagger can not inject ViewModel with KClass

I am moving my project java to kotlin, but got some confusion about KClass and Class
Here is my BaseActivity
abstract class BaseActivity<DB : ViewDataBinding, VM : BaseViewModel> : DaggerAppCompatActivity() {
private lateinit var mCustomDialog: CustomDialog
private lateinit var mViewDataBinding: DB
private lateinit var mViewModel : VM
#Inject
lateinit var viewModelFactory: ViewModelFactory
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Set Custom Dialog
mCustomDialog = CustomDialog(this, R.style.LoadingDialogStyle)
// Set ViewModel
mViewModel = ViewModelProviders.of(this, viewModelFactory).get(getViewModelClass().java)
// Set DataBinding
mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId())
mViewDataBinding.lifecycleOwner = this
mViewDataBinding.setVariable(getBindingVariable(), mViewModel)
mViewDataBinding.executePendingBindings()
// Initialize UI
prepareView(savedInstanceState)
}
#LayoutRes
abstract fun getLayoutId(): Int
protected abstract fun getViewModelClass(): KClass<VM>
abstract fun getBindingVariable(): Int
fun getViewModel(): VM {
return mViewModel
}
fun getViewDataBinding() : DB {
return mViewDataBinding
}
I am using protected abstract fun getViewModelClass(): KClass<VM> function for initializing ViewModel class in the function below
ViewModelProviders.of(this, viewModelFactory).get(getViewModelClass().java)
I use ViewModel in activities by this way
class SplashActivity : BaseActivity<ActivitySplashBinding, SplashViewModel>() {
override fun getViewModelClass(): KClass<SplashViewModel> {
return SplashViewModel::class
}
override fun getLayoutId(): Int {
return R.layout.activity_splash
}
override fun getBindingVariable(): Int {
return BR.vm
}
override fun prepareView(savedInstanceState: Bundle?) {
getViewModel().testLog()
}
}
But when I run the project, I got this error
error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an #Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.example.example.MyApp> {
^
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.example.example.utils.ViewModelFactory(viewModels)
com.example.example.utils.ViewModelFactory is injected at
com.example.example.base.BaseActivity.viewModelFactory
com.example.example.ui.splash.SplashActivity is injected at
dagger.android.AndroidInjector.inject(T) [com.example.example.di.AppComponent ? com.example.example.di.ActivityBindingsModule_SplashActivityInjector$app_debug.SplashActivitySubcomponent]
So I made some research and find out it is about KClass in my ViewModelKey
Here is ViewModelKey
#Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
#Retention(AnnotationRetention.RUNTIME)
#MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
If I do not change my code to Kotlin and use old Java class like this it works properly
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#MapKey
public #interface ViewModelKey {
Class<? extends ViewModel> value();
}
This is my ViewModelFactory class
#Suppress("UNCHECKED_CAST")
class ViewModelFactory #Inject
constructor(private val viewModels: MutableMap<Class<out ViewModel>, #JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val creator = viewModels[modelClass]
?: viewModels.asIterable().firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
?: throw IllegalArgumentException("unknown model class $modelClass")
return try {
creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
My SplashActivityModule
#Module
abstract class SplashActivityModule {
#Binds
#IntoMap
#ViewModelKey(SplashViewModel::class)
internal abstract fun provideSplashViewModel(splashViewModel: SplashViewModel) : ViewModel
}
So how can I use ViewModelKey properly with Kotlin and what is main cause of this error, any help will be appreciated
Your ViewModelKey be like
#MustBeDocumented
#kotlin.annotation.Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
#kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
#MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
As mentioned this question problem is related to Kotlin version. Using higher than 1.3.30 version solves the problem.

In TypeScript, how to prevent a method from being called on derived class?

There are three classes.
// in external library, which I don't want to modify
class ComponentBase {
// I want calling this to be disallowed
forceUpdate() {}
}
class ComponentBase_MyVersion extends ComponentBase {
// I want subclasses to always call this, instead of forceUpdate()
Update() {}
}
class MyComponent extends ComponentBase_MyVersion {
DoSomething() {
// I want this to be disallowed
this.forceUpdate();
// forcing the subclass to call this instead
this.Update();
}
}
How can I accomplish this, with changes only to ComponentBase_MyVersion?
Is there a way to "hide" a base-class member?
Or perhaps a way to override the definition -- like with the "new" keyword in C# -- letting me mangle the method definition to at least make warnings appear when attempting to call it?
The OOP does not allow you to do this kind of method cancellation. You can impleement this funcion on your class with an Exception like you suggested, or use a composition: https://en.wikipedia.org/wiki/Composition_over_inheritance
Example 1:
class ComponentBase {
forceUpdate() {}
}
class ComponentBase_MyVersion extends ComponentBase {
Update() {}
forceUpdate() {
throw new Error("Do not call this. Call Update() instead.");
}
}
class MyComponent extends ComponentBase_MyVersion {
DoSomething() {
// wil raise an exception
this.forceUpdate();
this.Update();
}
}
Example 2 (composition):
class ComponentBase {
forceUpdate() {}
}
class ComponentBase_MyVersion {
private _component: ComponentBase = ...;
Update() {}
// expose _component desired members ...
}
class MyComponent extends ComponentBase_MyVersion {
DoSomething() {
// compilation error
this.forceUpdate();
this.Update();
}
}
I hope I helped.
Encapsulate implementation by replacing inheritance with composition Delegation Pattern
You can do this by adding the private access modifier on the forceUpdate method. This will result in all the subclasses being unable to access forceUpdate. However TypeScript does not support package access modifiers, but you can do this by replacing inheritance with composition.
class ComponentBase {
forceUpdate() {
}
}
class ComponentBase_MyVersion {
// Replace inheritance with composition.
private component: ComponentBase;
Update() {
this.component.forceUpdate();
}
}
class MyComponent extends ComponentBase_MyVersion {
DoSomething() {
// Now subclass can't access forceUpdate method
this.Update();
}
}
Use a symbol in order to prevent external access to the method.
If you don't want to replace inheritance with composition, you can use Symbol to define a method. If your target is es5 you must configure tsconfig.json compilerOptions.lib to include es2015.symbol. Because every symbol is unique, any external module will not be able to obtain the symbol and access the method.
// libs.ts
let forceUpdate = Symbol("forceUpdate");
export class ComponentBase {
[forceUpdate]() {
}
}
export default class ComponentBase_MyVersion extends ComponentBase {
Update() {
this[forceUpdate]();
}
}
// test.ts
import ComponentBase_MyVersion from "./libs";
class MyComponent extends ComponentBase_MyVersion {
DoSomething() {
// Now subclass can't access the forceUpdate method.
this.Update();
}
}
I found a way that seems to work -- that is, which causes warnings to appear when someone attempts to call forceUpdate() on a subclass instance.
forceUpdate(_: ()=>"Do not call this. Call Update() instead.") {
throw new Error("Do not call this. Call Update() instead.");
}
Now when I write new MyComponent().forceUpdate(), I get a compiler error, with the warning message containing a description telling me to use Update() instead.
EDIT: Apparently this only works because the base class already had this definition:
forceUpdate(callBack?: () => any): void;
If instead the base method is defined with no arguments originally (as in the OP), the above solution doesn't work.
However, if you have a case like mine (where there's an optional property like that, which you can narrow the return-type of), it works fine. (not sure if this return-type-narrowing is a bug, or intended)

angular2 / typescript class inheritance with generic types

Hope one of you angular2 / typescript wizards can help out or at least provide a pointer in the right direction, before I got crazy :-)
Here is what I'd like to
have a parent class that implements it's own defined parent Interface, however using Generic Types so I can when creating a child class provide it with the child's specific and tailored class & data Interface.
the child class should be able to extend the parent data class by
being able to overwrite default/parent set variables
overwriting parent functions() and have the child's version called instead of the parent's default
In the below pseudo code example, I would like the call to the child's (inherited) someOtherfunction() to return "2"...
Am I asking for too much?
I can't seem to find any decent examples on the web...
How do I get this right?
Thank you -
Oliver
(CODE BELOW MAY BE BROKEN, IT'S JUST FOR ILLUSTRATION)
//
// Parent Class
//
export interface ICoreData <T> {
observeItems: Observable <T[]> ;
items: Array <T>;
}
#Injectable()
export class CoreData<T> implements ICoreData<T> {
public observeItems: Observable<T[]>;
private items: Array<T>;
constructor( 'Dependency Injection...' ) {}
coreFunction(): number {
return 1;
}
someOtherfunction(){
return this.coreFunction();
}
}
//
// Child class
//
export interface IMyDataStructure {
name: string;
age: string;
}
export interface ISpecificData extends ICoreData<IMyDataStructure> {
someExtraKey: number;
}
#Injectable()
export class SpecificData extends CoreData<IMyDataStructure> implements ISpecificData {
constructor() {
super();
}
coreFunction(): number{
//
// This function should "overwrite" the parent's original function
// and be called by the parent's someOtherfunction() function
//
return 2;
}
}
You're not asking too much. However you can't use interfaces to accomplish what you're trying to accomplish. You need to extend a class, which can be generic.
An interface is simply a contract, or a blueprint if you like, for a data type. There is no functionality associated with an interface. However in your case you wanted to be able to have methods on the base class; methods you could override in the derived.
The way I usually do this is to declare an abstract base class (so that the base class can't be instantiated itself), and then extend classes from that. Here's an example:
Note, I've removed all the Angular2 cruft in order to keep the example as simple as possible.
abstract class Base<T> {
constructor(public controlled: T) { }
doIt(): string {
return `Base.doIt: ${JSON.stringify(this.controlled)}`;
}
doSomethingElse(): string {
return `Base.doSomethingElse: ${JSON.stringify(this.controlled)}`;
}
};
interface Foo {
foo: string;
bar: string;
};
class Derived extends Base<Foo> {
constructor(foo: Foo) {
super(foo);
}
doSomethingElse(): string {
return `Derived.doSomethingElse: ${JSON.stringify(this.controlled)}`;
}
};
let d: Derived = new Derived({ foo: 'foo', bar: 'bar' });
console.log(`doIt ==> ${d.doIt()}`);
console.log(`doSomethingElse ==> ${d.doSomethingElse()}`);
Output:
doIt ==> Base.doIt: {"foo":"foo","bar":"bar"}
doSomethingElse ==> Derived.doSomethingElse: {"foo":"foo","bar":"bar"}
Playground link.

StructureMap InstanceInterceptor not being called

I want to intercept the creation of an instance in SM and I'm trying the following but it's not calling the InstanceInterceptor implementation, does anyone know why?
ForRequestedType<IPublishResources>()
.TheDefault
.Is
.OfConcreteType<PublisherService>()
.InterceptWith(new PublisherServiceInterceptor());
The test code uses the ObjectFactory to create instances, and is shown below:
// Given we have a configure object factory in StructureMap...
ObjectFactory.Configure(x => x.AddRegistry(new StructureMapServiceRegistry()));
// When we request a publisher service...
var publisher = ObjectFactory.GetInstance<IPublishResources>();
Cheers
AWC
I could not reproduce your problem in release 2.5.4. Here is my code.
public interface IPublishResources {}
class PublishResources : IPublishResources {}
public class LoggingInterceptor : InstanceInterceptor
{
//this interceptor is a silly example of one
public object Process(object target, IContext context)
{
Console.WriteLine("Interceptor Called");
return context.GetInstance<PublishResources>();
}
}
public class MyRegistry : Registry
{
public MyRegistry()
{
For<IPublishResources>()
.Use<PublishResources>()
.InterceptWith(new LoggingInterceptor());
}
}
[TestFixture]
public class Structuremap_interception_configuraiton
{
[Test]
public void connecting_implementations()
{
var container = new Container(cfg =>
{
cfg.AddRegistry<MyRegistry>();
});
container.GetInstance<IPublishResources>();
}
}
A question. Do you really need to use an Interceptor here? If you only need to define a factory you can do somethign like this.
public interface IPublishResourcesFactory
{
IPublishResources Create();
}
public class MyRegistry : Registry
{
public MyRegistry()
{
For<IPublishResources>().Use(c =>
{
return c.GetInstance<IPublishResourcesFactory>().Create();
});
//or
For<IPublishResources>().Use(c =>
{
//other object building code.
return new PublishResources();
});
}
}