How to create a custom class in NestJS and work with the instance of the class - class

I'm trying to create a helper class in NestJS which i can use in every file.
I tried to create the following class:
export class Logging {
public status: string;
private currentLog: Model<LogDocument>;
constructor(#InjectModel(Log.name) readonly log?: Model<LogDocument>) {
// Create a new log item when new instance of class is created
this.currentLog = new this.log({
title: 'New Log',
status: SyncStatusType.IN_PROGRESS,
startTime: new Date(),
});
}
public addCrashLog() {
// Update current log
}
public addSuccessLog() {
// Update current log
}
public finish() {
// Set status and update log
}
}
I want to be able to use this class in every other file and create a new instance of the class if necessary.
const newLog = new Logging();
newLog.addCrashLog();
....
Does someone have an idea how I can archive that with NestJS? Because I'm always having problems with dependency injection in NestJS when I'm trying to create a custom class.

First off, don't add the Logging class to any providers array, as that's what will tell Nest to create the instance. Next, if you're passing the values yourself, you don't need the #InjectModel() there's no need, as you're creating the class yourself. Lastly, just use the class as your example already shows, using the new keyword and handling the instantiation yourself. That should be all there is to it

Related

Inject service into class (not component) Angular2

I am struggling to find a way to inject a service into an class object in angular2.
* NOTE: This is not a component, just a class. *
export class Product {
id: number;
name: string;
manufacturer: string;
constructor(product: any) {
this.id = product.id;
this.name = product.name;
this.manufacturer = product.manufacturer;
}
The only solution I have come up with is to pass the service reference to the constructor whenever I create a new product... ie: instead of new Product(product) I would do new Product(product, productService) . This seems tedious and error prone. I would rather import the reference from the class and not messy up the constructor.
I have tried the ReflectiveInjector:
let injector = ReflectiveInjector.resolveAndCreate([ProductService]);
this.productService = injector.get(ProductService);
However, this creates an error No provider for Http! (ProductService -> Http) at NoProviderError.BaseError [as constructor] (Also I'm pretty sure this creates a new productService when I simple want to reference my singleton that is instantiated at the app level).
If anyone knows of a working solution I would be glad to hear it. For now i will pass the reference through the constructor.
Thanks
I was struggling with a similar issue, and what I ended up doing, was making the service a singleton as well as an Angular injectable.
This way you can inject via DI into Angular classes and call the static getInstance() method to get the singleton instance of the class.
Something like this:
import {Injectable} from "#angular/core";
#Injectable()
export class MyService {
static instance: MyService;
static getInstance() {
if (MyService.instance) {
return MyService.instance;
}
MyService.instance = new MyService();
return MyService.instance;
}
constructor() {
if (!MyService.instance) {
MyService.instance = this;
}
return MyService.instance;
}
}
There is no way to inject a service into a plain class. Angular DI only injects into components, directives, services, and pipes - only classes where DI creates the instance, because this is when injection happens.
To get Http from a custom injector, you need to add to it's providers like shown in Inject Http manually in angular 2
or you pass a parent injector that provides them
// constructor of a class instantiated by Angulars DI
constructor(parentInjector:Injector){
let injector = ReflectiveInjector.resolveAndCreate([ProductService]);
this.productService = injector.get(ProductService, parentInjector);
}
See also https://angular.io/docs/ts/latest/api/core/index/ReflectiveInjector-class.html

Set a key/id to a Workflow

New to Workflow Foundation, so it may be a basic question for many of you.
I have a workflow designer (client) /server application.
In the designer I can upload workflows to the server , which stores them in the DB. The designer can request to download a workflow from the server. Once downloaded , we can modify it in the designer and upload it again.
To be able to do that I need to add some sort of ID/Key to the workflow.
What's the best way to do that?
I was thinking about adding a property to the ActivityBuilder, but doing that adds it to the argument list, which doesn't seem right...
Any help would be much appreciated
Hi #Will, I gave it a go attaching the property to Activities but I can not get it working. I'm not using any models like WorkflowRecord, it's just a basic desginer.
I use _workflowDesigner.Save(path); to save it or _workflowDesigner.Load(path); to load it.
I create and add the attached property
attachProp = new AttachedProperty<int?>()
{
Name = "Key",
IsBrowsable = true,
Getter = (modelItem) => 5,
Setter = ((modelItem, keyValue) => modelItem.Properties["Key"].SetValue(keyValue)),
OwnerType = typeof(Activity)
};
_workflowDesigner.Context.Services.GetService<AttachedPropertiesService>().AddProperty(attachProp);
If I try to access the attached property, it throws me an exception (doesn't contain a definition for key)
dynamic mainActivity = ((_workflowDesigner.Context.Services.GetService<ModelService>().Root.GetCurrentValue() as ActivityBuilder).Implementation as Activity);
int? testValue = mainActivity.Key; //Exception, Activity' does not contain a definition for 'Key'
I read through this [post] (http://blogs.msdn.com/b/kushals/archive/2010/01/04/base-designer-with-additional-adornments.aspx) to add the attach property to the activity
Attached properties, via the AttachablePropertyServices Class.
public class WorkflowRecord
{
static AttachableMemberIdentifier Id =
new AttachableMemberIdentifier(typeof(Guid), "Id");
public static object GetCommentText(object instance)
{
object viewState;
AttachablePropertyServices.TryGetProperty(instance, Id, out viewState);
return viewState;
}
public static void SetCommentText(object instance, object value)
{
AttachablePropertyServices.SetProperty(instance, Id, value);
}
}
You can use this to get or set your database Id on an instance of the workflow, and it will be serialized/deserialized to/from xaml.
<Activity
xmlns:me="clr-namespace:Herp;assembly=derp"
me:WorkflowRecord.Id="This is a guid lol"
x:HideAdditionalAttributesBecauseThisIsAnExample="true" />
For more info, read this blog post on msdn

GWT - binding activityMapper with GIN not working

I´m trying to do my first steps with GWT/GIN.
I´ve downloaded the hellomvp example from google and followed this tutorial to get started with gin.
My problem is about this line in the configure-method of the HelloGinModule-class:
bind(ActivityMapper.class).to(AppActivityMapper.class).in(Singleton.class);
In my point of view it should bind my class "AppActivityMapper" as the active ActityManager.
But in fact the class constructor (or any method of the class) is never called, so the fired events are not caught.
The class AppActivityMapper looks like this:
public class AppActivityMapper implements ActivityMapper {
Provider<HelloActivity> helloActivityProvider;
Provider<GoodbyeActivity> goodbyeActivityProvider;
#Inject
public AppActivityMapper(final Provider<HelloActivity> helloActivityProvider, final Provider<GoodbyeActivity> goodbyeActivityProvider) {
this.helloActivityProvider = helloActivityProvider;
this.goodbyeActivityProvider = goodbyeActivityProvider;
}
#Override
public Activity getActivity(Place place) {
if (place instanceof HelloPlace) {
return helloActivityProvider.get();
} else if (place instanceof GoodbyePlace) {
return goodbyeActivityProvider.get();
}
return null;
}
}
In my example this code from my View-Class is called after clicking on a link:
presenter.goTo(new GoodbyePlace(name));
The event is fired to the event bus. But nothing happens.
Thanks in advance
You have defined an activity mapper somewhere in you GIN. But activity mapper have to be used in activity manager. Where do you create activity manager which will use your AppActivityMapper?
UPDATE:
The most logical thing is to keep activity manager out of the gin. E.g. in your ginjector you will have a method:
interface MyInjector extends Ginjector {
... //other methods
ActivityMapper getActivityMapper();
}
Than , when you create ginjector instance, you can create a manager and put correct activity mapper into it. for example:
MyInjector injector = GWT.create(MyInjector.class);
ActivityManager manager = new ActivityManager(injector.getActivityMapper(), injector.getEventBus());
If you have multiple managers and mappers, may be it will be better to extend ActivityManager class (so you can inject stuff into its constructor). Another solution is to use #Provides to initialize ActivityManager.

MEF: how to import from an exported object?

I have created a MEF plugin control that I import into my app. Now, I want the plugin to be able to import parts from the app. I can't figure how setup the catalog in the plugin, so that it can find the exports from the app. Can somebody tell me how this is done? Below is my code which doesn't work when I try to create an AssemblyCatalog with the current executing assembly.
[Export(typeof(IPluginControl))]
public partial class MyPluginControl : UserControl, IPluginControl
[Import]
public string Message { get; set; }
public MyPluginControl()
{
InitializeComponent();
Initialize();
}
private void Initialize()
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
CompositionContainer container = new CompositionContainer(catalog);
try
{
container.ComposeParts(this);
}
catch (CompositionException ex)
{
Console.WriteLine(ex.ToString());
}
}
}
You don't need to do this.
Just make sure that the catalog you're using when you import this plugin includes the main application's assembly.
When MEF constructs your type in order to export it (to fulfill the IPluginControl import elsewhere), it'll already compose this part for you - and at that point, will import the "Message" string (though, you most likely should assign a name to that "message", or a custom type of some sort - otherwise, it'll just import a string, and you can only use a single "string" export anywhere in your application).
When MEF composes parts, it finds all types matching the specified type (in this case IPluginControl), instantiates a single object, fills any [Import] requirements for that object (which is why you don't need to compose this in your constructor), then assigns it to any objects importing the type.

how to parametrize an import in a View?

I am looking for some help and I hope that some good soul out there will be able to give me a hint :)
I am building a new application by using MVVM Light. In this application, when a View is created, it instantiates the corresponding ViewModel by using the MEF import.
Here is some code:
public partial class ContractEditorView : Window
{
public ContractEditorView ()
{
InitializeComponent();
CompositionInitializer.SatisfyImports(this);
}
[Import(ViewModelTypes.ContractEditorViewModel)]
public object ViewModel
{
set
{
DataContext = value;
}
}
}
And here is the export for the ViewModel:
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(ViewModelTypes.ContractEditorViewModel)]
public class ContractEditorViewModel: ViewModelBase
{
public ContractEditorViewModel()
{
_contract = new Models.Contract();
}
}
Now, this works if I want to open a new window in order to create a new contract... or in other words, it is perfect if I don't need to pass the ID of an existing contract.
However let's suppose I want to use the same View in order to edit an existing contract. In this case I would add a new constructor to the same View, which accepts either a model ID or a model object.
"Unfortunately" the ViewModel is created always in the same way:
[Import(ViewModelTypes.ContractEditorViewModel)]
public object ViewModel
{
set
{
DataContext = value;
}
}
As far as I know, this invokes the standard/no-parameters constructor of the corresponding ViewModel at composition-time.
So what I would like to know is how to differentiate this behavior? How can I call a specific constructor during composition time? Or how can I pass some parameters during the Import?
I really apologize if this question sounds silly, but I have only recently started to use MEF!
Thanks in advance,
Cheers,
Gianluca.
You CAN do this. Check out the Messenger implementation in MVVM-Light. You can pass a NotificationMessage(Of Integer) to send the right ID to the view model. The view model has to register for that type of message, and load it when a message is sent.
MEF Imports by default only have a parameterless constructor.