Prism navigation/view discovery ignores container scopes - wpf

I am facing the following problem with Prism and DryIoC.
My contaier is set up with different scopes for reusing dependencies within those scopes. This works fine on injected dependencies. But as soon as I use Prisms navigation (_regionManager.RequestNavigate) or view discovery (_regionManager.RegisterViewWithRegion) mechanisms, this breaks up. I guess this is because both use the ServiceLoctor and the DryIocServiceLocatorAdapter resolves dependencies directly from the container.
Is there any built-in-option to make this work or any idea how to solve this in a good way?

Related

DotNetCore, Prism 7, WPF - Service Not Being Created

I'm using DotnetCore, WPF and Prism 7 to make a desktop application. I have one service called DbConnectionService that doesn't seem to be created. This service is not injected into any component that is reachable through the View tree(?). Instead, it listens to the IEventAggregator and communicates with the rest of the app through that.
I'm finding that I'm not able to get it to 1. be created, and 2. if it is created it doesn't stick around (GC I assume).
Below is the code I have "shotgunning" anything that will create the DbConnectionService. All to no avail.
containerRegistry.RegisterInstance(typeof(DbConnectionService), "DbConnectionService");
containerRegistry.Register<IDbConnectionService, DbConnectionService>();
containerRegistry.RegisterSingleton(typeof(DbConnectionService));
containerRegistry.GetContainer().RegisterSingleton<DbConnectionService>();
Any help on getting this service to be created and stick around is greatly appreciated.
This service is not injected into any component
That's why it's not created. Either you inject it and rely on the container's magic to create it, or you create it yourself.
You can use the container to keep the object alive (i.e. not garbage collected) through RegisterInstance:
containerRegistry.RegisterInstance( containerRegistry.GetContainer().Resolve<DbConnectionService>() );
Note that Resolve isn't on IContainerRegistry to prevent you from doing this, because you don't want to mix registering and resolving. If you have to, make 110% sure that all dependencies of DbConnectionService are registered beforehand.

How to share libraries across web components

I've started a micro frontends project by utilizing custom elements.
I'm looking for a way to share dependencies between all of the parts of the application.
I'm wondering how I could do this with Material-ui library.
For example one could attach library to the window object and access it from inside of the custom element (web component).
The problem that I'm seeing here is that the material-ui exists as a npm module, and I haven't managed to find an option to load it via script tag.
The custom elements are loaded via
http import
which means that they will be loaded before the window object has been populated with the material-ui library.
I found one way of sharing libraries, for example UI libraries, such as Material-UI, and that is by putting them on a global scope (window object).
Then the web component (custom element) which is being included in the composition layer can read it from the window object inherited from the context in which it's included.
This approach can be easily used in case when there is only functionality needed. In case of UI library, where there is style as well, one has to pay attention if the shadow dom is turned on or not on the web component, and turn it off if it is.
Reason for this is the web component's shadow dom styles scoping capability, meaning one can simply inherit styles from a parent.
Here's a quick sample that I've made last year and now I've just made it work again :) github.com/mnemanja/web-components-composition

Angular 2 - Including a provider in a service

I have a service loaded into a component as a provider. This service may return data using Http or it may not, the component should not care. However, it seems that the component itself must include HTTP_PROVIDERS if the loaded service uses Http. This breaks separation of concerns. What am I misunderstanding?
This breaks separation of concerns. What am I misunderstanding?
In order to support instantiating multiple instances of a service (i.e., so all services don't have to be singletons), an Angular app needs a way to specify multiple injectors (not just one). These injectors need to be created and configured in some kind of hierarchy. The component/directive tree, since it is a tree, already has a hierarchy. So Angular uses the (existing) component tree to configure dependency injection. I like to think of it as a sparser "injector tree" that overlays the component tree.
I think it would be more work to define a separate hierarchy for services – we, as developers, would probably have to define and configure another injector tree of some sort.
So instead of thinking of it as "components need to know the dependencies of services" (which, when stated that way, it does sound like we're breaking separation of concerns), I like to think of it more like the following: "when I write an Angular app, I have to configure my providers/dependencies on the injector tree"... and since the injector tree overlays the component tree, I use components to configure it.
But this is not ideal, since if you want to reuse components in a different app, you might need to change the providers arrays (i.e., you may need to reconfigure the injector tree).
In fact, it's better to specify the HTTP_PROVIDERS when bootstrapping your application:
bootstrap(AppComponent, [ HTTP_PROVIDERS ]);
But I agree with you that there are some impacts on having configuration of providers only on components.
The previous configuration will work because of hierarchical injectors.
See this question for more details about hierarchical injectors:
What's the best way to inject one service into another in angular 2 (Beta)?

Sprinkling Angular 2 components inside a non-angular page

Currently looking at upgrade paths from Angular 1 -> Angular 2 and one things we've done with our Angular 1 work is reuse some of our components on public facing non-app pages.
These pages are effectively static HTML (though they are rendered by Rails) and then some Angular 2 components are dropped into the page in places. This worked from with Angular 1, we simply bootstrapped the document element with a module that provided the directives and components we needed. There is no routing at all.
With Angular 2 it looks like it is all or nothing. You declare a single root component and everything is rendered through that. This would be a big shift for us and I'd like to avoid changing how we are doing things on these public facing pages.
Is it possible at all to just use Angular 2 components as needed in static HTML pages or will we need to move to a single root element SPA design?
In a nutshell, what I'm asking is if it is possible to have a mix of static content with dynamic angular components sprinkled within, or must all angular components live within a single root element on the page?
So this is simpler than I originally thought. In the Angular 2 docs it has some specific wording around bootstrapping multiple apps.
Bootstrapping Multiple Applications
When working within a browser window, there are many singleton
resources: cookies, title, location, and others. Angular services that
represent these resources must likewise be shared across all Angular
applications that occupy the same browser window. For this reason,
Angular creates exactly one global platform object which stores all
shared services, and each angular application injector has the
platform injector as its parent.
Each application has its own private injector as well. When there are
multiple applications on a page, Angular treats each application
injector's services as private to that application.
So it seems clear that this is intended to be possible and that multiple apps share service resources which is what I would hope for.
I've done some trivial tests with multiple bootstrapped components and it works fine. One thing I have not yet tried is bootstrapping an Angular 2 attribute directive for use outside of Angular 2 components. I suspect that won't work and that bootstrap only works with Components and not Directives.
In terms of guidance, I would suggest that Angular 2 is not really designed for sprinkling behaviour throughout a static page and probably should not be used that way. Rather, while you may have multiple sections of your paged defined by multiple apps, that components should make up nearly all of the document/interface.
we simply bootstrapped the document element with a module that provided the directives and components we needed. There is no routing at all
That's exactly how I'm currently using Angular2. See the example at https://github.com/niczero/ng2-es5-file-upload/blob/master/demo/index.html -- some of my 'static' pages are generated by perl in the same way you are using ruby.
As an aside, being able to use your modules both ways is much easier if you embrace Universal Module Definitions

Multiple *Window* App using Angular

We are designing a complex web app which runs in multiple browser windows .will use AngularJS
(note it has to look/feel like one app – just that it is spread across several browser windows)
Javascript allows a parent window to reference the objects on other windows as long as the parent retains references to the other windows. Those objects can be accessed either by the native accessors or, for example, by jQuery.
Is a multi-window app something that's been done with Angular before? How would such an app be structured to be scalable?
(I have seen the big 'angular-app' reference app which is a template for large scale apps (if I could only get it working!) but haven't found anything on using multiple browser windows...
Probably not the answer you're looking for, but from my experience w/ AngularJS it seems what you are looking for in an anti-pattern for angular. Specifically, angular is big on scoping - so a controller and view would only 'know' about its own stuff. Any other controllers/views on the same page, or other windows, etc. wouldn't necessarily have references to each other. Rather, an application on a page would have a $rootScope which can serve as a message bus w/ $emit(), on$().
So, perhaps look at this as loosely coupled parts with a centralized message bus that figures out which windows get what events. Then each part (app/controller/view) is just responding to those events.
Note: We had a test app that simulated multiple UIWebViews in a mobile app by hosting each angular app in and iFrames and used this approach successfully. Very composable, very testable.
HTH

Resources