I am using Windsor Castle as IoC tool. and uptill now I am able to inject dependencies into the targeted class easily. However what I am trying to do (and unable to do) is to inject single or multiple dependencies which are part of external DLLs loaded through reflection, but when I call the Resolve method of Container then it throws exception that:
Can't create component 'ClassLibrary3.MainClass' as it has dependencies to be satisfied.
Following is the peice of code that I am using
var assembly = Assembly.LoadFile(assemblyFullPath);
var type = assembly.GetType(fullyQualifiedClassName);
var container = new WindsorContainer();
container.Register(Component.For(type));
var dependecyInterfaceAssembly = Assembly.LoadFile("<SomePath>\\ClassLibrary3.dll");
var dependecyInterfaceType = dependecyInterfaceAssembly.GetType("ClassLibrary3.IDependency3");
var dependecyImplementationAssembly = Assembly.LoadFile("<SomePath>\\ClassLibrary3.dll");
var dependecyImplementationType = dependecyImplementationAssembly.GetType("ClassLibrary3.Dependency3");
container.Register(Component.For(dependecyInterfaceType).ImplementedBy(dependecyImplementationType));
return (IJob) container.Resolve(type);
So container calls the Resolve function it is throwing exception
Can't create component 'ClassLibrary3.MainClass' as it has dependencies to be satisfied.
'ClassLibrary3.MainClass' is waiting for the following dependencies:
- Service 'ClassLibrary3.IDependency3' which was not registered.
On the other hand I know for sure that all of its dependencies are referenced correctly (Path and Class names are checked).
Thanks in advance.
Related
In my WP8 app, I have MainView referencing MainViewModel. MainView is a menu where users can navigate to other views to do some tasks. Navigating from MainView works perfectly as I use ShowViewModel. However, navigating from other views when user completes a task, back to MainView using NavigationService.Navigate(URI) throws an exception "Unable to find incoming mvxviewmodelrequest".
To avoid this exception, I have construct the URI like below
var req = "{\"ViewModelType\":\"MyApp.Core.ViewModels.MainViewModel, MyApp.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\",\"ClearTop\":\"true\",\"ParameterValues\":null,\"RequestedBy\":null}";
NavigationService.Navigate(new Uri("/MainView.xaml?ApplicationUrl=" + Uri.EscapeDataString(req), UriKind.Relative));
Does anyone have a better way to use NavigationService.Navigate?
Most navigations in the MvvmCross samples are initiated by either MvxAppStart objects or by MvxViewModels. Both of these classes inherit from MvxNavigatingObject and use the ShowViewModel methods exposed there - see https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNavigatingObject.cs
From MvxNavigatingObject, you can see that MvvmCross routes the navigation call to the IMvxViewDispatcher which in WindowsPhone is a very thin object - all it does is marshall all calls to the UI thread and to pass them on to the IMvxViewPresenter - see https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxPhoneViewDispatcher.cs
The presenter is an object created in Setup - and the default implementation uses an IMvxPhoneViewModelRequestTranslator to convert the navigation call into a uri-based navigation - see https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxPhoneViewPresenter.cs
Silverlight/WindowsPhone then uses this uri for navigation, creates the necessary Xaml page, and then calls OnNavigatedTo on this page. As part of the base.OnNavigatedTo(); handing in MvxPhonePage, MvvmCross then calls the OnViewCreated extension method. This method checks if there is already a ViewModel - if there isn't one then it attempts to locate one using the information in the uri - see https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxPhoneExtensionMethods.cs
With this explanation in mind, if any app ever wants to initiate an MvvmCross navigation from a class which doesn't already inherit from MvxNavigatingObject - e.g. from some Service or from some other class, then there are several options:
You can provide a shim object to do the navigation - e.g.:
public class MyNavigator : MvxNavigatingObject {
public void DoIt() {
ShowViewModel<MyViewModel>();
}
}
// used as:
var m = new MyNavigator();
m.DoIt();
You can instead use IoC to locate the IMvxViewDispatcher or IMvxViewPresenter and can call their Show methods directly
var request = MvxViewModelRequest<MyViewModel>.GetDefaultRequest();
var presenter = Mvx.Resolve<IMvxViewPresenter>();
presenter.Show(request);
You can write manual code which mimics what the IMvxViewPresenter does - exactly as you have in your code - although it might be "safer" to use the IMvxPhoneViewModelRequestTranslator.cs to assist with generate the url - see https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/IMvxPhoneViewModelRequestTranslator.cs
var request = MvxViewModelRequest<MyViewModel>.GetDefaultRequest();
var translator = Mvx.Resolve<IMvxPhoneViewModelRequestTranslator>();
var uri = translator.GetXamlUriFor(request);
One other option that Views always have is that they don't have to use the standard MvvmCross navigation and ViewModel location. In WindowsPhone, your code can easily set the ViewModel directly using your own logic like:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (ViewModel == null) {
ViewModel = // something I locate
}
// if you are doing your own logic then `base.OnNavigatedTo` isn't really needed in winphone
// but I always call it anyway
base.OnNavigatedTo(e);
}
Alternatively in WindowsPhone, you can even replace MvxPhonePage with a different base class that uses it's own logic for viewmodel location. This is easy to do in WindowsPhone as all Xaml pages have built-in data-binding support.
i have a little problem with getDefinitionByName.
My purpose is to instantiate an FXG object(Number10.fxg) in a document mxml on runtime.
The name of the Class is in a string variable that is used by getDefinitionByName
to return the name of the class to insantiate. The code doesn't work even if doesn't send an error message. The code is as follows:
import assets.Number10;
import flash.utils.getDefinitionByName;
import mx.core.IVisualElement;
private function onClick(event:MouseEvent):void
{
var value:String = "Number10";
var ClassDefinition:Class = getDefinitionByName(value) as Class;
var ten:IVisualElement = new ClassDefinition() as IVisualElement;
this.contentGroup.addElement(ten);
}
I tried also with... var ten:IVisualElement = new ClassDefinition();
but nothing. It Doesn't work!
Please, Help me!
First of all, i refer to the adobe documentation pages that covering the topic so telegraphic. Here it is:
Option includes class [...]
Description Links one or more classes to the resulting application SWF file, whether or not those classes are required at compile time.
To link an entire SWC file rather than individual classes, use the include-libraries option.
Ok.In Flash Builder i go to the Additional compiler arguments where there is just this option
-locale en_US
So i add my option under this
-includes class = assets.Number10
or
-includes class assets.Number10
or
-includes class Number10
When the application runs i get the Error #2032.
I think that the option declaretion is wrong. I do not have a good reference for using option.
So...Help me!
How can i declare the Number10 class or the assets package with the other fxg object using the includes class option?
Ok! I find the solution...
Is to put a reference to Number10 class somewhere in the code, for instance:
import assets.Number10;
import flash.utils.getDefinitionByName;
import spark.core.SpriteVisualElement;
//case1
var myNumber:Number10;
//or
//case2
Number10;
private function onClick(event:MouseEvent):void
{
var value:String = "assets.Number10";
var ClassDefinition:Class = getDefinitionByName(value) as Class;
var ten:SpriteVisualElement = new ClassDefinition() as SpriteVisualElement;
this.contentGroup.addElement(ten);
}
and the code works :-)
This is a problem that comes from the way that Flex compiles its code. Flex compiles its code so that if a class is not used, it will keep this class off the final compiled program.
But the problems are not over yet! If i have hundreds of Fxg objects that could be instantiate, declaring all classes is little difficult and tedious.
So, how i can delclare in one time all classes of a package?
You can add classes to SWCs and SWFs using the include and includeClasses compiler options. Using these, you don't have to reference the classes in the code. Consult the documentation for proper usage.
Be sure to use the fully qualifed class name.
Also, the approach of casting your FXG class as an IVisualElement is new to me. I thought you had to use real classes in casting and the sort. Try using a SpriteVisualElement.
private function onClick(event:MouseEvent):void
{
var value:String = "assets.Number10";
var ClassDefinition:Class = getDefinitionByName(value) as Class;
var ten:IVisualElement = new ClassDefinition() as SpriteVisualElement.;
this.contentGroup.addElement(ten);
}
UPDATE: Now I've moved the AMFConnection var declaration to outside the functions in Main, and commented out some trace() commands, and now it gives new errors:
Error #2044: Unhandled NetStatusEvent:. level=error, code=NetConnection.Call.BadVersion
at AMFConnection/init()[/Users/Jan/Downloads/amfphp1/AMFConnection.as:32]
at AMFConnection()[/Users/Jan/Downloads/amfphp1/AMFConnection.as:23]
at Main/testConnection()[/Users/Jan/Downloads/amfphp1/Main.as:14]
at Main()[/Users/Jan/Downloads/amfphp1/Main.as:10]
All of these essentially point to AMFConnection's NetConnection initialisation: _netConnection = new NetConnection(); (where _netConnection is declared at the beginning of the class)
I'm trying to connect to AMFPHP on a server (with Flash AS3), and the swf borks when it reaches the .connect() stage. To make things easier (?) and more reusable (?), I've put all the NetConnection mechanics into a separate class, AMFConnection, which I call from the Main document class like this (details changed):
public function testConnection(e:*=null):void {
var conn:AMFConnection = new AMFConnection();
conn.table = "some_table";
conn.selections = "*";
conn.conditionals = "WHERE something = 'something'";
conn.service = "QueryAMF";
conn.method = "makeQuery";
conn.displayText = txt;
conn.gogogo("http://www.someplace.com/Amfphp");
}
AMFConnection actually starts the connection and calls the AMFPHP service with the function gogogo(), and here's where the connect() NetConnection function just won't work. Here's the main section of the AMFConncection class
private var _netConnection:NetConnection;
private var _responder:Responder;
function AMFConnection()
{
init();
}
private function init(e:* = null)
{
_netConnection = new NetConnection();
_responder = new Responder(uponResult);
}
public function gogogo(url:String):void {
trace(url);
_netConnection.connect(url);
_netConnection.call(String(service+"/"+method), new Responder(onResult, null), table, selections, conditionals);
}
A quick debug session reveals the below errors:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at AMFConnection/gogogo()[AMFConnection.as:44]
at Main/testConnection()[Main.as:20]
at Main()[Main.as:8]
Where: Main.as:20 = conn.gogogo(...), and AMFConnection.as:44 = _netConnection.connect(url);
It also fails to display the stage, instead showing the loading dots. Now, eventually I'm going to move this application to the same server as the AMFPHP service, but even when I try it there with a relative url, instead of an absolute one, it still breaks down at connect(). I've tried changing the publish settings from local only to network only, to no avail.
Any clues? Know a better way to connect to AMFPHP locally?
Cheers in advance!
JB
P.S. Post updated, see top of page.
first, i prefer to use a php file which contains my sql and params. but hey...
The most obvious reason why you might get this error would be a fault in the url i guess. I believe that the standaard gateway.php is written without a capital G. and does not situate itself in the core folder but in the amfphp folder. but then again I don't know what you have altered.
Your _netConnection must be null, and you call connect() method on null reference, so you finish with NullPointerException. Show us how you initialize _netConnnection :).
Ok, I basically remade the thing, and after a couple of hours, it decided to work. I'm not sure how, but... eh.
Thanks all for your help
in my context:
var parserManager:ParserManager = injector.instantiate(ParserManager);
parserManager.injector = injector;
injector.mapValue(ParserManager, parserManager);
in my parserManager(doesn't extend any other class) class:
public var injector:IInjector;
the parserManager is injected in some models.
Is there a better way of doing it? this is so dirty..
injector.mapSingleton(ParserManager);
var parserManager:Parser = injector.getInstance(ParserManager);
in ParserManager:
[Inject]
public var injector:IInjector
I am a little suspect of injecting the injector into a class with Manager in its name, but that is about the cleanest way I can think of to get it done.
You should keep in mind that after the manager has been mapped, if you don't need it immediately then it will be injected with the injector when it is first created (by being injected in another class that uses it). Robotlegs creates instances lazily.
I have two SWFs: main.swf and external.swf. main.swf needs to access some methods in external.swf, so it loads external.swf into itself and uses getDefinitionByName("package.Class") to access the class and one of its methods:
var ExternalClass = getDefinitionByName("package.Class") as Class;
var ClassInstance = new ExternalClass();
var NeededFunction:Function = ClassInstance["NeededFunction"] as Function;
var response:String = NeededFunction(param);
Now, I need to extend the functionality of NeededFunction (which is a public method)... I know it's possible to override public methods, but how would I go about this with a dynamically loaded class?
I was thinking I could do something like this, but it doesn't work:
var ClassInstance["NeededFunction"] = function(param1:uint):String {
var newString = "Your number is: "+param1.toString(); //New functionality
return newString;
}
Another way to deal with this could be to have the classes in a package that's accessible by both SWFs. Just add the classes' root folder to your Actionscript path .
Instead of getting a class by using getDefinitionByName , you simply import it. As for overriding , you can create a Class that overrides one of the classes , or you can create an Interface.
import com.yourlocation.ExternalClass;
var external:ExternalClass = new ExternalClass();
Using FlashDevelop this is pretty simple to fix.
Right click your included swc from the Project list.
Choose options then "include library (complete library)".
..you can now use getDefinitionByName to get a unreferenced class from your swc file.