I recently converted from MEF to Unity - for various reasons.
I previously had a IMenuService object in a module that I exported with MEF and imported in other modules. I believe what I have to do with Unity is take the unity container in as a parameter to the constructor of my module, then use that to register the IMenuService , however, I'm not sure how to do this (what argument type? do I have to first register the container in the bootstrapper to import it into the module?)
Also, in MEF there are ModuleDependency attributes to make sure other modules are loaded first... what would be the equivolent in Unity?
EDIT: figured out the IUnityContainer argument... however, still curious about the seconds part... dependencies
as you have figured out, the type you should have your modules depend on to IUnityContainer. You don't really have to register the container with itself in order to be able to work with it in the modules (while you can do it if you wanted, and to make things clearer). And last, module dependencies are independent from the IoC container you're using, so it should work just fine. You can as well configure the ModuleCatalog from xaml using:
protected override IModuleCatalog CreateModuleCatalog()
{
return ModuleCatalog.CreateFromXaml(new Uri("catalog.xaml", UriKind.Relative));
}
and in the catalog.xaml file, you can specify the dependencies using the DependsOn property of the ModuleInfo.
hope this helps :)
Related
I have a problem with dependency injection in my project. I use PRISM framework in my project and I chose Ioc container when create it. Link -> https://github.com/blackpantific/InstagroomEX
In my app.xaml file I associate the class and interface
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation();
containerRegistry.RegisterForNavigation<WelcomeView, WelcomeViewModel>();
containerRegistry.RegisterForNavigation<RegistrationView, RegistrationViewModel>();
containerRegistry.RegisterForNavigation<LoginView, LoginViewModel>();
//regestering
containerRegistry.RegisterSingleton<IValidationService, ValidationService>();
}
But my page after initializing() doesn't appear at the screen. This is ViewModel constructor
public RegistrationViewModel(INavigationService navigationService, IUserDataService userDataService,
IValidationService validationService) :
base(navigationService)
{
_userDataService = userDataService;
_validationService = validationService;
}
Something wrong here. When I pass to the RegistrationViewModel() constructor another parameters besides INavigationService navigationService the RegistrationView page doesn't not displayed. What am I doing wrong?
Assuming that WelcomePage is displayed correctly and RegistrationPage is not, I think that Andres Castro is correct: Prism tries to resolve the IUserDataService which is not possible. In the debug output you should see a message that IUserDataService cannot be resolved.
(Note: The following is based on my experiences with Prism and Unity. This might hold for other Dependency Injection frameworks, but it's possible that other frameworks behave differently.)
Prism relies on a Dependency Injection (DI) framework, for example Microsofts Unity application block. What happens when you try to navigate to RegistrationPage is, that Prism (if you are using ViewModelLocator.AutowireViewModel="True") tries to determine the type of the viewmodel (by convention) and asks the underlying DI framework to resolve this type (i.e. create an instance). For each of the required constructors parameters of this type, then again the DI framework tries to resolve them. If the parameters require concrete types it will then try to resolve those. If the parametery require interface (or abstract) types, the DI framework will look at its registrations and if the types have been registered create instances according to this registrations (which in turn might involve resolving other types).
If - however - the parameter requires an interface type which has not been registered, the DI framework does not know how to handle the situation. It coulld of course assume null, but this might lead to errors that might be way harder to track down, hence it will throw an exception (which is swallowed and Logged by Prism).
Now how can you handle the situation?
You'll need to tell the DI framework how to resolve IUserDataInterface. Since RegistrationPageViewModel does not actually use it, you could register null
containerRegistry.RegisterInstance<IValidationService>(null);
Could be irritating later, though. I'd rather remove the dependency of RegistrationPageViewModel to IUserDataService altogether - for now and add it later when it's actually used - or create a mock/stub that implements IUserDataService and is used as long there is no real implementation. This would be registered with the DI framework as you did with IValidationService.
Still exploring the new ASP.NET MVC5, now with build in DI!
No Problem so far, I can just inject my Handlers (I don't like the Term Service, since this defines to me a Platform-Neutral Interface):
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<Model.Meta.AppSettings>(Configuration.GetSection("AppSettings"));
services.AddSingleton(typeof(Logic.UserEndPointConfigurationHandler));
services.AddSingleton(typeof(Logic.NetworkHandler));
services.AddMvc();
}
Works fine, also the strongly typed Configuration-Object "AppSettings" works perfectly fine.
Also the Injection in the Controllers works as well.
But now my collaps: I seperated my DataAccess from the Handlers, and obviously I'd like to inject them as well:
public class UserEndPointConfigurationHandler
{
private readonly DataAccess.UserEndPointAccess _access;
public UserEndPointConfigurationHandler(DataAccess.UserEndPointAccess access)
{
_access = access;
}
But bam, UserEndPointAccess can't be resolved. So it seems like even I directly request to DI an Class with a Parameterless-Constructor, I need to register that. For this case, sure I should Interface and register them, but what does that mean for internal helper classes I also inject?
According to the Docs: http://docs.asp.net/en/latest/fundamentals/dependency-injection.html#recommendations and also the examples I found, all people in the world only seem to communicate between Controllers and some Repositories. No Business-Layer and no Classes on different Abstraction-Levels in Assemblies.
Is the Microsoft DI approach something totally differnt than the good ol' Unity one, where I can really decouple as fine granular as I'd like to?
Thanks in advance.
Matthias
Edit #Nightowl: I add my answer here, since it's a bit longer.
First of all, Unity does automatically create Instances, if I request a conecrete Type. This allows me to inject Types I register and Types, like Helper classes etc. I don't need to. This combination allows me to use DI everywhere.
Also in your Example I'd need to know the DataAcces in the WebGui, which is quite thight coupled. Well, I know there are solutions for this via Reflection, but I hoped Microsoft did something in this Topic, but probably that'd mean to big of a change.
Also allows Unity to store Instances or Instructions how to create them, another huge feature, which is missing at the moment.
Probably I'm just to spoiled, what refined DI-Libraries do, probably they also do to much, but at the moment the Microsoft-Implementation is just a huge downgrade according to my Information.
MVC Core follows the the composition root pattern, which is where object graphs are created based off of a set of instructions to instantiate them. I think you are misinterpreting what the IServiceCollection is for. It does not store instances, it stores instructions on how to create instances. The instances aren't actually created until a constructor somewhere in the object graph requests one as a constructor parameter.
So, in short the reason why your service (which you call UserEndPointAccess) is not being instantiated when you request it is because you have not configured the IServiceCollection with instructions on how to create it.
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<Model.Meta.AppSettings>(Configuration.GetSection("AppSettings"));
services.AddSingleton(typeof(Logic.UserEndPointConfigurationHandler));
services.AddSingleton(typeof(Logic.NetworkHandler));
// Need a way to instantiate UserEndPointAccess via DI.
services.AddSingleton(typeof(DataAccess.UserEndPointAccess));
services.AddMvc();
}
So it seems like even I directly request to DI an Class with a Parameterless-Constructor, I need to register that.
If you are doing DI correctly, each service class will only have a single constructor. If you have more than one it is known as the bastard injection anti-pattern, which essentially means you are tightly coupling your class definition to other classes by adding references to them as foreign defaults.
And yes, you need to register every type you require (that is not part of MVC's default registration). It is like that in Unity as well.
I am loading a type from an external assembly and want to create an instance of the type. However, this type/class is setup for constructor injection by objects currently being managed/bound by Ninject. How can I use Ninject to create an instance of this type and inject any constructor dependencies?
Below is how I get this type.
Assembly myAssembly = Assembly.LoadFrom("MyAssembly.dll");
Type type = myAssembly.GetType("IMyType");
Assuming you've created a Kernel, you should be able to create and have it resolved via:
kernel.Get(type)
.... then I read the question.... Assuming MyAssembly.dll has an implementation of IMyType, you need (in your main assembly) :-
kernel.Load( "MyAssembly.dll")
And in your dynamically loaded assembly:-
public class Module : StandardModule
{
public override void Load()
{
Bind<IMyType>().To<MyType>();
}
}
And dont forget to see if MEF is the answer here, as you dont want to go writing reams of explicit plugin management and/or detection logic if you can help it (but if you're just doing straightforward stuff and are only doing the Assembly.LoadFrom() for the purposes of asking the question, you're probably still in Ninject's sweet spot.
Ditto, if you actually need to resolve an interface via Assembly.GetType(), you probably should be using something like dynamic to do the late binding you'll probably have to do (and before you know it you should be using a dynamic language or hosting a scriopting language)
I am developing a dynamic mocking framework for Flex/AS3 and am having trouble with private/support types (ie. those declared outside the package {} in a class file).
In my ABC "file", I am declaring the instance with the PROTECTED_NAMESPACE class flag and with a PRIVATE_NS multiname. I have also experimented with giving it the same namespace as the class it is subclassing (eg. PRIVATE_NS("ContainerClass.as$123")).
No matter what I do, I always get the following error after loadBytes:
VerifyError: Error #1014: Class ContainerClass.as$123::PrivateClass could not be found.
I have experimented with loading the generated bytecode into the same ApplicationDomain as the private class (I use a child domain by default). I even tried registering a class alias before the load (though that was a bit of a stretch).
Am I forgetting anything or is it simply a restriction of the AVM?
Please note that I am fully aware that this is illegal in ActionScript 3.0, I am looking for whether this is actually possible in the AVM.
Edit: For those interested in the work so far, the project is asmock and is on sourceforge.
I'm no expert with ABC files but I just don't think this is possible in the AVM2. I did several tests a while ago with the AS3 Eval lib and they all failed.
Related to dynamic mocking, I have filed an issue in Adobe bugbase, asking for a dynamic proxy mechanism: http://bugs.adobe.com/jira/browse/ASC-3136
I'm not sure what you mean by PRIVATE_NS("ContainerClass.as$123"), My reading of avm2overview.pdf 4.4.1 is that private namespaces are not permitted to have a name, hence that the "<class name>$<number>" namespace in debug output is generated for your convenience. I would assume that would mean you would have to hack your abc into the same abc tag in the source swf to access the namespace constant index (and that sounds too much like hard work to me!)
I haven't actually managed to generate a loading swf, though, so take this with a grain of salt.
Having gone back to look at this problem in ernest, I can definitively answer this question: private classes can only be referenced from the LoaderContext that loaded them
I have been able to add support for private interfaces by reproducing the interface in the loaded ABC 'file', but it cannot be coerced/cast back to the original private interface.
This is still useful for my requirements, as a private interface can be used to combine multiple interfaces.
I have a Flex application where load time is extremely important (consumer site). i want to be able to get something up on screen and then allow additional modules to be loaded as necessary.
The issue I'm facing is that the sum total of all the modules is much larger than if i were to include all the components in a single .swf file.
Its pretty obvious why. For instance the classes needed for web service access seem to take about 100kb. If I dont use those classes in my main.swf then they'll be included in EVERY module that uses them. So if I have 5 modules thats an extra 500kB wasted.
In theory I want 3 levels
main.swf - minimum possible layout / style / font / framework type stuff
common.swf - additional classes needed by module 1 + module 2 (such as web services)
module1.swf - module 1 in site
module2.swf - module 2 in site
I dont know if this is even possible.
I'm wondering if I can load swz/swf files for portions of the framework instead of the entire framework.
I really need to get my main app size down to 200Kb. It grows to 450kb when I add web services and basic datagrid functionality.
Any lessons learned would be appreciated.
I know this was awhile ago, but I figured I'd post another response in case anyone is still looking for an answer on this.
I've been looking into optimizing Flex apps and, after some checking into it, have decided to use Modules. Primarily 'cause they have such good options for optimization.
The two mxmlc commands you need are:
mxmlc -link-report=MyAppReport.xml MyApp.mxml
and
mxmlc -load-externs=MyAppReport.xml MyModule.mxml
My external swf (using the Flex Framework) is now only 21k. It's doing much (yet), but even as it does more and more, it will continue to use resources from the main app code.
Here's the batch file I created to speed up the process (you have to have put mxmlc in your Environment Path variable for it to work like this. Control Panel -> System -> Advanced -> Environment Variables, Edit the Path System Variable, adding the path to your mxmlc (requires a reboot)):
cd C:\Projects\MyProject\Develop\Modules
mxmlc -link-report=MyAppReport.xml C:\Projects\MyProject\Develop\Source\Main.mxml
mxmlc -load-externs=MyAppReport.xml MyModule.mxml
move /Y MyModule.swf ..\Runtime\Modules
More info here:
http://livedocs.adobe.com/flex/3/html/help.html?content=modular_4.html
Hope that helps!
Flex is a bit of a pig when it comes to file size. There really is only one way to get your app sizes down and that is to use an external swz for the framework. There is an Adobe Devnet article on Improving Flex application performance using the Flash Player cache which I recommend you read.
On a project I worked on we had problems with our preloading module sucking in classes that we didn't want. What we had to do was create interfaces to the classes that resided in the other modules and reference them that way. When the module is loaded we simply assigned a reference to the IApplicationModule in order to call our initialization code.
Also look into putting your classes into a seperate SWF file and then use ApplicationDomain to get access to the classes
(this code taken from this forum post which explains how to access classes loaded from modules in Flex)
private function loadContent(path:String):void
{
var contentLoader:Loader = new Loader();
contentLoader.contentLoaderInfo.addEventListener(
Event.COMPLETE,
loadContent_onComplete);
contentLoader.load(new URLRequest(path));
}
private function loadContent_onComplete (event:Event):void
{
var content:DisplayObject = event.target.content;
if(content is IFlexModuleFactory)
{
var content_onReady:Function = function (event:Event):void
{
var factory:IFlexModuleFactory = content as IFlexModuleFactory;
var info:Object = factory.info();
var instanceClass:Class = info.currentDomain.getDefinition(
info.mainClassName) as Class;
addChild (new instanceClass ());
}
content.addEventListener ("ready", content_onReady);
}
else
{
addChild (content);
}
}
There is an option on the command-line compiler to exclude class definitions that are already compiled into another swf. It works like this:
Compile the Main Application (which contains a loader) and opt to generate a report.
Compile the Module and opt to exclude classes in the above report.
You could look into the ModuleLoader class, maybe you can load up your core stuff in the first 200kbs then load the rest when and if it's needed.
Also it's worth bearing in mind that any SWC's you use are embedded at compile time whereas any SWF's are loaded at runtime.