Angular dart: How to inject a service in a multi level package environment - angular-dart

Dart 2.0.0
Angular 5
I have an application divided into two packages.
Let's say that we have package A and package B, that depends on package A.
In package A I have a class that uses the service "ServiceA".
Now, in package B I have a service called "Service B" that extends "serviceA". I would like to inject "service B" instead of "serviceA" every time that in package A "serviceA" is used.
I tried to configure my packageB.AppComponent providers this way:
ClassProvider(ServiceB),
ClassProvider(package_a.ServiceA, useClass: ServiceB)
and, in a certain way, it works.
The above statements say: use an instance (of ServiceB) when you encounter a ServiceB declaration or use another instance of ServiceB when you have to inject a ServiceA class.
But I need something diffrent.
Inside classA I have defined serviceA as a provider, because I want that every time that classA is called, a different instance of ServiceA is created (and ServiceB when called from package B).
If I use packageA alone, it works fine, when I run packageB and I call classA, I cannot get an instance of ServiceB, but always an instance of serviceA.
How can I solve this? Is there something wrong in the way I have understood DI?
Edit 1:
Ted suggestion was not so clear to me, so I did a couple of tests and then I succeeded, but I do not really like the solution I found.
First I added this lines In ServiceA class:
Function serviceAFactoryFunction = () => ServiceA();
ServiceA ServiceAFactory() => serviceAFactoryFunction();
const ServiceAProvider = FactoryProvider(ServiceA, ServiceAFactory);
The idea here is to decouple the function that generates the service (() => ServiceA()) from ServiceAFactory, so that I can inject (manually...) the correct function in package B.
Inside classA I removed the
providers: [
ClassProvider(ServiceA)
and I set the ServiceAProvider
providers: [
ServiceAProvider
In ServiceB I added the following:
Function serviceBFactoryFunction = () => ServiceB();
ServiceB ServiceBFactory() => serviceBFactoryFunction();
const ServiceBProvider = FactoryProvider(ServiceB, ServiceBFactory);
Only the first line here is strictly needed, but I added the other just in case tomorrow I could have a package C inheriting from this service.
Last step, in package B, in AppComponent class,
I removed the providers I defined:
ClassProvider(ServiceB), ClassProvider(package_a.ServiceA, useClass:
ServiceB)
And I changed the constructor injecting the correct function:
AppComponent() {
package_a.serviceAFactoryFunction =
serviceBFactoryFunction;
}
This way it works, but I do not really like all this extra code to be generated.
Any other solution?

For the case of wanting a different instance of a class I would suggest using factories instead of separate providers. Especially if you want to always have a different instance regardless of where you are in the injection tree. This way you can specify only one provider at the root and still get separate instances no matter where in the tree you are.

Related

how init a val out the object in scala?

A redis cluster client should should be shared in many place,am I right? with the google, so I use a RedisCli object:
object RedisCli {
val jedisClusterNodes = new java.util.HashSet[HostAndPort]()
jedisClusterNodes.add(new HostAndPort("192.168.1.100", 6379))
lazy val jedisCluster = new JedisCluster(jedisClusterNodes)
//...method with jedisCluster
}
the problem is how can I init the jedisCluster out the object--I want init the HostAndPort in the main method of other object, get the ip from properties file the file passed by command line. should I just use class RedisCli in my circumstance?
I think I am totally lost in class and object.
In Scala all members of a singleton objects should be defined. While you are allowed to modify var members from the outside, take a step back and ask yourself what is the point of having a singleton object in your case if each client can modify its members? You will only end up with spaghetti code.
I would highly recommend using a dependency injection framework (Spring for example) where you can create beans in a specific place then inject them where you need them.
In a nutshell singleton objects should be used when you want to define methods and values (never seen a case where a var is used) that are not specific to each instance of a class (think Java static). In your case, you seem to want different instances (otherwise why should they be set from client code) but want a certain instance to be shared across different clients and this is exactly what dependency injection allows you to do.
If you don't want to use a DI framework and are okay with having clients modify your instances as they please, then simply use a class as opposed to an object. When you use the class keyword, different instances can be instantiated.
class RedisCli(val ip: String, val port: Int) {
val hostAndPort: HostAndPort = new HostAndPort(ip, port)
etc...
}
Hope this helps.

How to avoid multiple instances of a service in Angular Dart

It seems that each component that creates its own instance of [a] service. I don't understand why.
I note this AngularJs 2 - multiple instance of service created, but I'm not clear on the correct solution. Do I create the service instance _myService in main:
void main() {
bootstrap(AppComponent,[MyService]);
}
and then copy it to [child] components (because I also remove MyService from the component providers)? This doesn't seem correct, because the components reference _myService before it's instantiated, and I have to check it for being null.
Thanks
Steve
You can use factory constructor pattern like here.
Creating your service in the bootstrap will make sure there is only one instance of it for the app (if you don't provide it again in some component).
You get multiple copies of it only if you provide it in some #Component - then each instance of the component (and all its children) will have a separate instance of the service.

Difference between this and window

Imagine that coffeescript class :
class Batman
constructor: ->
alert "Batman is awesome"
I think it's a rookie question, but what's the real difference between :
class #Batman
constructor: ->
alert "Batman is awesome"
and
class window.Batman
constructor: ->
alert "Batman is awesome"
Compile your coffeescript using the '-c' argument and see what you get:
(function() {
/// Your code here
}).call(this);
That this there is the context of the function wrapper being called, and becomes the this object inside your coffeescript module.
In the context of a browser, your module is initialized with the global this = window; in the context of a Node or IoJS, this = global, the global context of execution; in the context of plv8, this = role, a per-execute object that contains security information (since plv8 is basically node run inside a SQL server, this is important to have).
class window.Batman explicitly attaches your Batman class to a window object (which means you no longer have isomorphic code you can use everywhere); class #Batman attaches it to the local context, which can be, well, whatever you want it to be.
All in all, as a best practice, attaching stuff to VM-supplied contexts (like the browser, your node instance, your database) is generally not a good idea, and you should find a better way to instantiate your code and pass it from module to module.

How to call constructor with interface arguments when mocking a concrete class with Moq

I have the following class, which uses constructor injection:
public class Service : IService
{
public Service(IRepository repository, IProvider provider) { ... }
}
For most methods in this class, I simply create Moq mocks for IRepository and IProvider and construct the Service. However, there is one method in the class that calls several other methods in the same class. For testing this method, instead of testing all those methods together, I want to test that the method calls those methods correctly and processes their return values correctly.
The best way to do this is to mock Service. I've mocked concrete classes with Moq before without issue. I've even mocked concrete classes that require constructor arguments with Moq without issue. However, this is the first time I've needed to pass mocked arguments into the constructor for a mocked object. Naturally, I tried to do it this way:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
However, that does not work. Instead, I get the following error:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: My.Namespace.Service.
Could not find a constructor that would match given arguments:
Castle.Proxies.IRepository
Castle.Proxies.IProvider
This works fine if Service's constructor takes simple arguments like ints and strings, but not if it takes interfaces that I'm mocking. How do you do this?
Why are you mocking the service you are testing? If you are wishing to test the implementation of the Service class (whether that be calls to mocked objects or not), all you need are mocks for the two interfaces, not the test class.
Instead of:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
Shouldn't it be this instead?
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Service(repository.Object, provider.Object);
I realize that it is possible to mock concrete objects in some frameworks, but what is your intended purpose? The idea behind mocking something is to remove the actual implementation so that it does not influence your test. But in your question, you have stated that you wish to know that certain classes are called on properly, and then you wish to validate the results of those actions. That is undoubtedly testing the implementation, and for that reason, I am having a hard time seeing the goals of mocking the concrete object.
I had a very similar problem when my equivalent of Service had an internal constructor, so it was not visible to Moq.
I added
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
to my AssemblyInfo.cs file for the implementing project. Not sure if it is relevant, but I wanted to add a suggestion on the off chance that it helps you or someone else.
It must be old version issue, all is ok with latest version. Nick, Please check!
P.s.: I started bounty by misstake (I had wrong signature in my constructor).

How to carry out custom initialisation with autofac

I'm adding autofac to an existing project and some of the service implementations require their Initialize method to be called and passed configuration information. Currently I'm using the code:
builder.Register(context =>
{
var service =
new SqlTaxRateProvider(context.Resolve<IUserProvider>());
service.Initialize(config);
return service;
}
).As<ITaxService>()
.SingleInstance();
which works but I'm still creating the object myself which is what I'm trying to get away from this and allow autofac to handle it for me. Is it possible to configure a post create operation that would carry out the custom initialisation?
To give you an idea of what I'm after ideally this would be the code:
builder.RegisterType<SqlTaxRateProvider>()
.As<ITaxService>()
.OnCreated(service=> service.Initialize(config))
.SingleInstance();
Update:
I am using Autofac-2.1.10.754-NET35
.OnActivating(e => e.Instance.Initialize(...))
should do the trick.
You might also investigate the Startable module (see the Startable entry in the Autofac wiki).
Mark's suggestion to do initialisation in the constructor is also a good one. In that case use
.WithParameter(new NamedParameter("config", config))
to merge the config parameter in with the other constructor dependencies.