DryIoc registering default primitives - dryioc

I have a boostrapper for the Caliburn.Micro MVVM framework where I just auto register all ViewModels in the assembly.
Some ViewModels have constructors with parameters, and I usually overwrite these manually (using the Register-parameter ifAlreadyRegistered: IfAlreadyRegistered.Replace) after my auto-registration is complete.
However, when a ViewModel has a primitive type, DryIoc automatically fills the type with a default value.
When I then manually register the ViewModel with the correct parameter, I get two registrations for the same ViewModel, where Caliburn.Micro will chose the default-filled one.
What is the proposed method of dealing with this stuff?
UPDATE:
ctor ViewModel(DependencyA depA, string[] list)
AssemblySource.Instance.SelectMany(Portable.GetAssemblyTypes)
.Where(type => type.Name.EndsWith("ViewModel"))
.ForEach(type => _container.Register(type));
This get registered as ServiceKey=DefaultKey.Of(0) registered as factory
So I now know what list should be (after the auto-registration), and I register ViewModel again, this time with a different service-key which is linked to the actual string[].
Container.Register<ViewModel>(
made: Parameters.Of.Type<IEnumerable<string>>(typeof(string[])),
serviceKey: "list");
This results in another registration with ServiceKey="list" registered as factory. I would like this named registration to replace the default, but I have to keep the name to actually populate the list.
The reason: Caliburn.Micro will attempt to resolve by type, and I would explicitly have to use Caliburns IoC.Get<>() to provide the key which would mean that I could not inject the ViewModel in the constructor.

As the first attempt, you can try to solve the problem head on: via using container-wide factory selector rule SelectKeyedOverDefaultFactory:
var c = new Container(Rules.Default
.WithFactorySelector(SelectKeyedOverDefaultFactory("preferable key")));
c.Register<I, A>();
c.Register<I, B>(serviceKey: "preferable key");
c.Resolve<I>(); // will resolve I of B
c.Register<X>();
c.Resolve<X>(); // will work as before (w/out rule) by falling back to default factory.
But I plan another way of solving such cases in the next version.

Related

Ember: adding a mixin to a class after it's been created

I want to add a mixin to an Ember class which has already been created. (The class is defined in a library, actually Ember itself; it's LinkView).
I see that we can do mixin.apply(obj), but this applies the mixin to an instance of the class. I want to add the mixin to the class, so it's automatically mixed-in to all newly created objects.
I attempted to override the init method of the class, using reopenClass, and do mixin.apply(this) there, to apply the mixin to the instance, and then call the original init method, but this does not seem to work because the mixin wiring is set up in the init method and it's already too late by the time I can get to it.
reopenClass does not seem to accept a mixin argument like extend does. Its code seems to suggest that it's doing something with mixins, but whatever it is it doesn't work:
a = Ember.Object.extend().reopenClass(Ember.Mixin.create({mixval: 1});
a.create().get('mixval'); // undefined
I know that I could create my own class with MyLinkView = Ember.LinkView.extend(mixin, ..., but unfortunately the original class name is referenced explicitly within the library, so I really would prefer to figure out how to extend that original class with my mixin.
I experimented with Ember.LinkView = Ember.LinkView.extend(mixin, .... This somehow seems dangerous, although it seems to work. But in this particular case it doesn't help me since the reference within the Ember code (in the definition of the {{link-to}} helper) is to an internal version of the class, not the fully qualified Ember.LinkView.
Any ideas?
The solution is simply
Klass = Parent.extend({init: {...}});
Mixin = Ember.Mixin.create({init: {...}});
Klass.reopen(mixin);
Everything works as expected, including the super chain. In other words, a call to Klass.create().init() will call the mixin's init, and a call to super from there will call the original Klass#init.
In the course of researching this question, I discovered something interesting about reopen. Even if the argument is not a mixin, it is treated as one (internally, it actually creates a temporary one). This means that if you do
Klass.reopen({
init: function() {
this._super.apply(this, arguments);
}
});
The call to super is actually calling the original init, not the init in the parent class. In other words, specifying init in a reopen does not replace the existing init on the class, it more or less layers on top of it. I can't see this behavior documented anywhere in the Ember docs, but it does seem useful in the right situation.

getting error 'Microsoft.Practices.ServiceLocation.ActivationException' occurred in Microsoft.Practices.ServiceLocation.dll

I am Unit Testing MVVM based application that uses prism and using mocking to test view model . I am able to call the constructor of my viewmodel class by passing mock objects of region manager and resource manager but when control goes inside constructor it fails at the following statement :
private EventAggregator()
{
this.eventAggregatorInstance = ServiceLocator.Current.GetInstance<IEventAggregator>();
} It gives error : An unhandled exception of type 'Microsoft.Practices.ServiceLocation.ActivationException' occurred in Microsoft.Practices.ServiceLocation.dll
Additional information: Activation error occured while trying to get instance of type IEventAggregator, key "". Please help how to resolve this.
I see you solved your problem by adding the EventAggregator to your container.
However, I would suggest that your ViewModel should not be using the ServiceLocator to resolve the EventAggregator at all. The ServiceLocator is a glorified static instance that is basically an anti-pattern (see Service Locator is an Anti-Pattern). Your ViewModel should most likely accept the EventAggregator in the constructor via dependency injection and use it from there. I don't think you should need a container to test your ViewModels. You could just construct them with their constructors and pass them any mock implementations of their dependent objects (as parameters to the constructor).
Based on my understanding, the Service Locator gets initialized when running and initializing the Bootstrapper. Therefore, the exception you are issuing would be caused by not having the Locator initialized.
I believe the following post would be useful considering the non-Prism alternative taking into account that you didn't run the Bootstrapper on the Unit Test scope:
EventAggregator and ServiceLocator Issue
You would need to set the EventAggregator in the Mock Container, and then set the Service Locator service for that container:
(Quoted from above link)
IUnityContainer container = new UnityContainer();
// register the singleton of your event aggregator
container.RegisterType( new
ContainerControlledLifetimeManager() );
ServiceLocator.SetLocatorProvider( () => container );
I hope this helped you,
Regards.

const-correctness when passing complex types

So, I have four classes:
App - this represents the entry-point for the application
MainPage - this represents the home screen
Authenticator - this represents a helper/utility class for authentication
LoginPage - this represents a login screen.
App, MainPage, and LoginPage all have pointers to an Authenticator, and it is, in-fact, passed from App, to MainPage, to LoginPage as the user starts the app, reaches the main screen, and is prompted to log in. App creates MainPage, and if MainPage needs to log in, it creates LoginPage. The Authenticator pointer is passed at creation.
Let's say Authenticator looks something like this:
class Authenticator {
public:
std::string GetToken() const;
void Login(std::string username, std::string pass);
}
Now, App will create a normal, non-const pointer to Authenticator but because I don't want MainPage to be able to modify Authenticator, I want it to store a const pointer to it (ie so it can only call const member functions on it). However, I would like LoginPage to be able to call non-const member functions, like Login(), so when I pass my Authenticator from MainPage to LoginPage, I'll need to cast away the const-ness.
My question is: is it bad to do so in this situation? Should a class that is not allowed to modify an object be able to pass it to one that can? Or would it be better to have App create MainPage and LoginPage at the same time, and give them both the same Authenticator to start with? My only problem with that option is that I create a LoginPage actively, rather than lazily, and I'd prefer to do it lazily.
Thanks in advance.
From the Apps point of view, MainPage is modifying the Authenticator. If it's doing so directly or calling another party (LoginPage) to do it on it's behalf doesn't matter. So MainPage should get a non-const pointer and should then pass this to it's sub page for login.
If you want to make sure that your MainPage does not modify the Authenticator, you could implement a base class for it that stores this pointer and has a method to call the login dialog. The Authenticator is private, the method is protected. You can then derive your own MainPageDerived which has no (legal, non-hacky) chance to modify Authenticator but can call LoginPage if needed.
Note that I said could because for 3 classes I would think that's way overengineered. However, if you have more pages in the future, that may be a valid approach.
You're missing an important part of the concept of logical constness. When a class accepts a pointer (or reference) to a const object, it's promising NEVER to use the pointer/reference in a way that could modify the object. This of course means passing along to someone else who could modify it.
In other words, if MainPage is planning to ask someone to modify the Authenticator for it (that is, pass a non-const pointer to it to someone else), it's also responsible for the modifications, and should thus be storing a non-const pointer to it.
From an interface point of view: if you have MainPage(
Authenticator const* ), you are promessing that nothing MainPage
does will modify the observable state of Authenticator.
Directly or indirectly—if MainPage later passes its
pointer to another class which will modify the object, you've
violated the contract. Thus, in your case, it const-correctness
requires MainPage( Authenticator* ): the code constructing
MainPage doesn't care whether the modifications are direct or
indirect; it just wants to know what the contract is, and that
it is upheld.
Give MainPage only what it needs. You can look at this a few ways. It could need:
An AuthenticationTokenSource which provides an up-to-date Token.
An AuthenticatedExectuor which performs Actions which MainPage defines, but AuthenticatedExectuor provides the authentication as it calls the Action
There are probably other ways, but those are the first that spring to mind.

Adding custom functions to Ember.js ArrayControllers

I'm trying to figure out Ember.js and keep hitting what seems like basic problems that are not documented in a way I understand.
I want a object to manage a list of stuff. ArrayController seems to make sense. I assume having that controller load the data from the 3rd party server (youtube) makes the most sense. So My plan is to write some custom functions in the controller to load the data.
App.videoController = Ember.ArrayController.extend({
loadSomeVideos() {
console.log("I have run");
}
});
after I run the above code App.testController.someFunction() does not exist. Why not? I feel like I am missing some basic concept.
When you call Ember.ArrayController.extend, you're actually just extending the class not creating a concrete instance, therefore you can't call loadSomeVideos.
There are a few conventions in Ember that can get you stumped if you're unaware of them. As commented by "Unspecified", you should use the following convention to extend the class.
Please note the upper case VideoController and also the way in which I'm defining the loadSomeVideos method:
App.VideoController = Ember.ArrayController.extend({
loadSomeVideos: function() {
console.log("I have run");
}
});
Now, if you want to run this, you need to create an instance of the App.VideoController class. Once again notice the capitalisation:
App.videoController = App.VideoController.create();
So, I use a lower case v for the instance, and an upper case V for the class. I've just created an instance (App.videoController) of the class (App.VideoController).
To call your method, you need to call it from the instance, like this:
App.videController.loadSomeVideos();
Check out the following two pages in the documentation.
This first page gives you some info about extending classes and then instantiating them so you can call their methods:
http://emberjs.com/guides/object-model/classes-and-instances/
The second page goes into a bit of depth about more advanced methods reopen and reopenClass.
http://emberjs.com/guides/object-model/reopening-classes-and-instances/

How to dynamically call a method from a different component by using cfscript?

I'm looking for the best way to dynamically call a method from a different component in cfscript. Notice that it's concerning a method in a different component. So far I've tried 3 different methods, but none of them seem be exactly what I'm looking for:
All cases are written in cfscript inside a component method. Let's say I'm trying to dynamically call the setName(required string name) method in the MyComponent component. All cases have following variables defined:
var myComp = new MyComponent();
var myMethod = "setName";
var args = {"name"="foo"};
use evaluate() for the job
evaluate("myComp.#myMethod#(argumentCollection=args)");
pros: is done with very little code
cons: code is not very 'clean' and use of evaluate() seems to have an 'evil' reputation in the online community. I wouldn't want my code to be evil.
use a cfml wrapper for <cfinvoke>
invoke("MyComponent", myMethod, args);
pros: I can use all functionality of cfinvoke
cons: It creates a new instance of MyComponent with every invoke.
create a dynamicMethod method in MyComponent
myComp.dynamicMethod(myMethod, args);
dynamicMethod of MyComponent:
public any function dynamicMethod(required string methodName, required struct argumentColl){
var cfcMethod = variables[arguments.methodName];
return cfcMethod(argumentCollection=arguments.argumentColl);
}
pros: I can finally call myComp directly. Most comfortable solution so far.
cons: I can now call private methods of MyComponent via dynamicMethod.
(I've also tried the 'function as variable' solution outside of MyComponent, but then the function looses its working context. e.g. if MyComponent would extend a component, the 'super' scope would no longer refer to the extended component).
None of these solutions seem to be perfect, so is there no other way to call a dynamic function from a different controller?
And if there isn't, which one of these is the best solution?
Any advice is welcome, thanks.
Good analysis.
One thing you could do here is to more-closely emulate <cfinvoke> with your wrapper function. <cfinvoke> will take either a component path or a component instance (ie: an object) in that COMPONENT attribute. So your 'con' of 'It creates a new instance of MyComponent with every invoke.' isn't really valid.
ColdFusion 10, btw, adds a invoke() function to achieve just this. I note you're on CF9, so this is no help to you. But it's perhaps relevant for other people who might land on this question.