Dynamic loading of modules in Silverlight using Prism and Unity - silverlight

The basic idea that I'm trying to accomplish is to configure my Silverlight app to resolve its dependencies at runtime (without having to add references to dependent DLLs in the project).
I have my UI project that references an infrastructure project than contains various interfaces (e.g. repositories). Concrete implementations of these interfaces are stored in separate SL apps that I want to download and link to at runtime. I want to be able to configure my UI app from an external config file so that I can switch from one interface implementation to another at runtime without having to recompile the app.
What I have done so far is to create a Prism module for each implementation (in a separate SL app) and get those XAPs hosted in my web project. In my UI app I created a boostraper that has this:
protected override IModuleCatalog CreateModuleCatalog()
{
var mc = Microsoft.Practices.Prism.Modularity.ModuleCatalog.CreateFromXaml(new Uri("/UI;component/Repositories/ModulesCatalog.xaml", UriKind.Relative));
return mc;
}
ModulesCatalog.xaml looks like this:
<Modularity:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:Modularity="clr-namespace:Microsoft.Practices.Prism.Modularity;assembly=Microsoft.Practices.Prism">
<Modularity:ModuleInfo Ref="ImplementationOne.xap"
ModuleName="ImplementationOne"
ModuleType="ImplementationOne.Module, ImplementationOne, Version=1.0.0.0" />
</Modularity:ModuleCatalog>
In my ConfigureContainer override I have:
protected override void ConfigureContainer()
{
var unity = Unity.CreateFromXaml(new Uri("/UI;component/Repositories/UnityConfiguration.xaml", UriKind.Relative));
unity.Containers.Default.Configure(Container);
Container.RegisterInstance<Unity>(Unity.ConfigurationKey, unity);
base.ConfigureContainer();
}
But the unity.Containers.Default.Configure(Container) throws that the assembly cannot be found. (If I manually add the DLL to UI.xap file this works so I guess I'm missing something as the XAP is either not being downloaded or the assembly is not getting registered).
I've been struggling with this for a week now, read lots of SO topics but still cannot solve the problem. All the examples that I have found contain direct project refrences which is exactly what I'm trying to avoid.
Thanks!

To do assembly discovery and dynamic XAP loading you should use MEF container, not Unity.
See more information from official source: http://msdn.microsoft.com/en-us/library/ff921140(v=PandP.40).aspx

Related

Resource not loaded with PrismApplication (Prism v7 - 7.0.0.329-ci)

Using the new Prism v7 library, the Bootstrapper class is obsolete and must be replaced by the PrismApplication class.
I configured the new PrismApplication for my app but the app failed to load the XAML resources at the right time.
I declare a few resources in the App.xaml file:
<local:MyPrismApplication x:Class="Xxx.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Xxx">
<local:MyPrismApplication.Resources>
...
</local:MyPrismApplication.Resources>
</local:MyPrismApplication>
The new PrismApplication creates the Shell. The Shell need resources that aren't yet loaded.
Using the 'old' bootstrapper class, the problem doesn't exist.
What is recommended with the new PrismApplication class? Can we not set up anymore the resources in the App.xaml ?
Actually, you may have found a bug. I changed the startup process to start in the Ctor, not in the OnStartup override. I should probably change it back to do everything in OnStartup instead, similar to the bootstrapper. This will ensure all resources are available. Can you submit a bug on the GitHub site?
https://github.com/prismlibrary/prism/issues
EDIT: Just updated the PrismApplication class. Try the latest CI build and see if it works.

Integrate an MVVM WPF Solution with Caliburn Micro and MEF into an old WPF Applicaion with codbehind and Page Navigation

Last year I built a WPF application using page navigation and no MVVM.
Recently I was asked to build a new application for the same customer which I did in WPF MVVM with Caliburn Micro and MEF. Now my customer asks me to integrate the new application into the old one.
My thought was to add a new page to the old application and to integrate the shell of the new application into a ContentControl of this page.
My problem now is that the old application is started by an
<StartupUri="Views\NavWindow.xaml">
entry in the app.xaml, while the new application is started by a bootstrapper like
<local:AppBootstrapper x:Key="bootstrapper" />
where AppBootstrapper looks like
class AppBootstrapper : Bootstrapper<ShellViewModel>
{
private CompositionContainer container;
protected override void Configure()
{
container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));
CompositionBatch batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(container);
container.Compose(batch);
}
protected override object GetInstance(Type serviceType, string key)
{
string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
var exports = container.GetExportedValues<object>(contract);
if (exports.Count() > 0)
{
return exports.First();
}
throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
}
}
So, as far as I understand, in case of the new app the bootstrapper initializes the whole app, calls the ShellViewModel and eventually the ShellView.
Because I use the EventAggregator in the new app to send messages from one viewmodel to another, I think I canĀ“t just get rid of the bootstrapper and use the view-first model of Caliburn Micro.
So my problem is: can I call the bootstrapper from my old app by myself, and if so, where should I store the instance of it, and how do I tell Caliburn Micro where to put the ShellView?
Any help is appreciated.
CM is so light that in these situations it's actually worth having a peek at the source to see what a particular class is actually doing.
The Bootstrapper works because declaring it in the resources file of the application forces an instantiation of it. The constructor calls Start on the instance and that sets up the aggregator, IOC, etc.
https://caliburnmicro.codeplex.com/SourceControl/changeset/view/4de6f2a26b21#src/Caliburn.Micro.Silverlight/Bootstrapper.cs
If you were to load the application into a ContentControl in another application, I can't see a reason why it wouldn't kick off CM as the resources for the loaded application would still be processed, instantiating and starting up the Bootstrapper etc. Have you tried it in a test project? That might be your first option.
There may be some areas where CMs default implementation of Bootstrapper might not be ideal, but on first glance I can't see any glaring issues (not sure what happens to the application events such as OnStartup etc when you load a sub-application so you might want to look at that). Worst case you can roll your own Bootstrapper for the sub-app and just rebuild with the tweaked functionality.

Can't get pack Uri to work

I've got a WPF application I'm building. The solution contains a WPF control library project called CustomControls. There's a folder under the CustomControls project folder called Layouts. There's an XML file in that folder called OnscreenLayout.xml. The Build Action property for this file is set to Embedded Resource.
I'm trying to load that file into a stream in the code behind and pass the stream on to a method of a third party library class. The code in question looks like this:
OnscreenKeyboard.DefaultLayout = FPS.VirtualKeyboard.KeyboardLayout.Create(
App.GetResourceStream(
new Uri( #"/CustomControls;component/Layouts/OnscreenLayout.xml",
UriKind.Relative ) ).Stream );
When this code runs, it throws an IOException with the message
Cannot locate resource 'layouts/onscreenlayout.xml'.
I've even tried using this string for the Uri:
#"pack://application:,,,/CustomControls;component/Layouts/OnscreenLayout.xml"
But no joy. What am I doing wrong?
Edit: I have even tried changing the build action for the file from "Embedded Resource" to "Resource" and it still doesn't work.
Thanks
Tony
Only Content and Resource build actions are valid for resource files used in WPF application.
Please avoid other build actions such as Embedded Resource - this will work as well with appropriate API, but it is not favored by WPF.

How to access web application class into silverlight application

I am beginner in silverlight..I have created a silverlight project. When a new silverlight project is created it is automatically creating a silverlight application and one web application. I have added a class in both applications. Now I want to access a method of web application class into silverlight application class. Is it possible? I have tried to add web application reference to silverlight but VS is not allowing. Is there any another way to do??
What you need is called WCF. A really simple tutorial that should get you going is found here: How to call WCF methods from Silverlight controls
Fundementally WCF allows the silverlight client to make method calls on a class instance hosted on the web site.
Yes it is possible, but not in the normal way. A Silverlight assembly can only reference another Silverlight assembly (this is a limitation of VS2008, i don't know if it has been changed in VS2010).
What you need to do is add an existing file to your Silverlight project, when the file browse dialog opens you navigate to the class file you want to reuse, but instead of just clicking the Add button, click on the little down arrow on the button and choose Add as link - now the file will "exist" in both projects and can be used in both.
If you are going to do this repeatedly though, you will want to move those shared class files out into a separate assembly, do a project reference from your web app, and have the equivalent Silverlight class library mirroring it (sharing the files as links), and then project reference that Silverlight class library from your Silverlight app.

Silverlight WebPart in SharePoint

I'm making a WebPart for SharePoint that will instantiate a Silverlight UserControl and feed it some data. My problem is that when I have created my sample-WebPart and just instantiate a Silverlight control, the webpart, when added to a page or displayed in the webpart gallery, instead of rendering blank, renders an error page saying "File Not Found". No clue in the logfiles to what file was not found or why this error is thrown. Here is my code:
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.SilverlightControls;
namespace TestSLWP {
public class CustomWebPart1 : WebPart {
protected override void CreateChildControls() {
Label lblHello = new Label();
lblHello.Text = "Hello";
Controls.Add(lblHello);
Silverlight sl = new Silverlight();
}
}
}
I've added references to System.Web.Extensions and System.Web.Silverlight to the project. They are in the GAC, and the webpart is written and compiled on the same computer that SharePoint resides. If I change the CreateChildControls() to be:
protected override void CreateChildControls() {
Silverlight sl = new Silverlight();
sl.ID = "CustomWebPart1SL";
sl.Source = "/Silverlight/CustomWebPart.xap";
this.Controls.Add(sl);
}
I get the same error. Also if I remove the first slash in sl.Source I get the same error, even though the file is present in a virtual directory in the same application pool as SharePoint. I therefore, and because the error comes with just instantiating the Silverlight object, believe that the file that cannot be found is not my XAP.
What file can't SharePoint find and what can I do about it?
Here's the error message:
http://www.freeimagehosting.net/uploads/2dca8dbdfb.png
Hi I found a complete walk through on how to get Silverlight web parts get running on your application: http://www.vbforums.com/archive/index.php/t-557072.html
As you can see there are added some more things to the web.config beside your assembly registration.
Enabling SilverLight requires a lagre amount of web config modifications. Did you add those?
There could be the problem with your storage folder with silverlight control. You must register path to this storage as safe in web.config (for example find in web.config line with "~/controltemplates").

Resources