How to dynamically discover all XAML files in all modules in a Silverlight prism app - silverlight

Is there an easy way to dynamically discover all the XAMLs files within all the currently loaded modules (specifically of a Silverlight Prism application)? I am sure this is possible, but not sure where to start.
This has to occur on the Silverlight client: We could of course parse the projects on the dev machine, but that would reduce the flexibility and would include unused files in the search.
Basically we want to be able to parse all XAML files in a very large Prism project (independent of loading them) to identify all localisation strings. This will let us build up an initial localisation database that includes all our resource-binding strings and also create a lookup of which XAML files they occur in (to make editing easy for translators).
Why do this?: The worst thing for translators is to change a string in one context only to find it was used elsewhere with slightly different meaning. We are enabling in-context editing of translations from within the application itself.
Update (14 Sep):
The standard method for iterating assemblies is not available to Silverlight due to security restrictions. This means the only improvement to the solution below would be to cooperate with the Prism module management if possible. If anyone wants to provide a code solution for that last part of this problem there are points available to share with you!
Follow-up:
Iterating content of XAP files in a module-base project seems like a really handy thing to be able to do for various reasons, so putting up another 100 rep to get a real answer (preferably working example code). Cheers and good luck!
Partial solution below (working but not optimal):
Below is the code I have come up with, which is a paste together of techniques from this link on Embedded resources (as suggested by Otaku) and my own iterating of the Prism Module Catalogue.
Problem 1 - all the modules are
already loaded so this is basically
having to download them all a second
time as I can't work out how to
iterate all currently loaded Prism modules.
If anyone wants to share the bounty
on this one, you still can help make
this a complete solution!
Problem 2 - There is apparently a bug
in the ResourceManager that requires
you to get the stream of a known
resource before it will let you
iterate all resource items (see note in the code below). This means I have to have a dummy resource file in every module. It would be nice to know why that initial GetStream call is required (or how to avoid it).
private void ParseAllXamlInAllModules()
{
IModuleCatalog mm = this.UnityContainer.Resolve<IModuleCatalog>();
foreach (var module in mm.Modules)
{
string xap = module.Ref;
WebClient wc = new WebClient();
wc.OpenReadCompleted += (s, args) =>
{
if (args.Error == null)
{
var resourceInfo = new StreamResourceInfo(args.Result, null);
var file = new Uri("AppManifest.xaml", UriKind.Relative);
var stream = System.Windows.Application.GetResourceStream(resourceInfo, file);
XmlReader reader = XmlReader.Create(stream.Stream);
var parts = new AssemblyPartCollection();
if (reader.Read())
{
reader.ReadStartElement();
if (reader.ReadToNextSibling("Deployment.Parts"))
{
while (reader.ReadToFollowing("AssemblyPart"))
{
parts.Add(new AssemblyPart() { Source = reader.GetAttribute("Source") });
}
}
}
foreach (var part in parts)
{
var info = new StreamResourceInfo(args.Result, null);
Assembly assy = part.Load(System.Windows.Application.GetResourceStream(info, new Uri(part.Source, UriKind.Relative)).Stream);
// Get embedded resource names
string[] resources = assy.GetManifestResourceNames();
foreach (var resource in resources)
{
if (!resource.Contains("DummyResource.xaml"))
{
// to get the actual values - create the table
var table = new Dictionary<string, Stream>();
// All resources have “.resources” in the name – so remove it
var rm = new ResourceManager(resource.Replace(".resources", String.Empty), assy);
// Seems like some issue here, but without getting any real stream next statement doesn't work....
var dummy = rm.GetStream("DummyResource.xaml");
var rs = rm.GetResourceSet(Thread.CurrentThread.CurrentUICulture, false, true);
IDictionaryEnumerator enumerator = rs.GetEnumerator();
while (enumerator.MoveNext())
{
if (enumerator.Key.ToString().EndsWith(".xaml"))
{
table.Add(enumerator.Key.ToString(), enumerator.Value as Stream);
}
}
foreach (var xaml in table)
{
TextReader xamlreader = new StreamReader(xaml.Value);
string content = xamlreader.ReadToEnd();
{
// This is where I do the actual work on the XAML content
}
}
}
}
}
}
};
// Do the actual read to trigger the above callback code
wc.OpenReadAsync(new Uri(xap, UriKind.RelativeOrAbsolute));
}
}

Use GetManifestResourceNames reflection and parse from there to get only those ending with .xaml. Here's an example of using GetManifestResourceNames: Enumerating embedded resources. Although the sample is showing how to do this with a seperate .xap, you can do this with the loaded one.

I've seen people complain about some pretty gross bugs in Prism
Disecting your problems:
Problem 1: I am not familiar with Prism but from an object-oriented perspective your Module Manager class should keep track of whether a Module has been loaded and if not already loaded allow you to recursively load other Modules using a map function on the List<Module> or whatever type Prism uses to represent assemblies abstractly. In short, have your Module Manager implement a hidden state that represents the List of Modules loaded. Your Map function should then take that List of Modules already loaded as a seed value, and give back the List of Modules that haven't been loaded. You can then either internalize the logic for a public LoadAllModules method or allow someone to iterate a public List<UnloadedModule> where UnloadedModule : Module and let them choose what to load. I would not recommend exposing both methods simultaneously due to concurrency concerns when the Module Manager is accessed via multiple threads.
Problem 2: The initial GetStream call is required because ResourceManager lazily evaluates the resources. Intuitively, my guess is the reason for this is that satellite assemblies can contain multiple locale-specific modules, and if all of these modules were loaded into memory at once it could exhaust the heap, and the fact these are unmanaged resources. You can look at the code using RedGate's .NET Reflector to determine the details. There might be a cheaper method you can call than GetStream. You might also be able to trigger it to load the assembly by tricking it by loading a resource that is in every Silverlight assembly. Try ResourceManager.GetObject("TOOLBAR_ICON") or maybe ResourceManager.GetStream("TOOLBAR_ICON") -- Note that I have not tried this and am typing this suggestion as I am about to leave for the day. My rationale for it being consistently faster than your SomeDummy.Xaml
approach is that I believe TOOLBAR_ICON is hardwired to be the zeroth resource in every assembly. Thus it will be read very early in the Stream. Faaaaaast. So it is not just avoiding needing SomeDummy.Xaml in every assembly of your project that I am suggesting; I am also recommending micro-optimizations.
If these tricks work, you should be able to significantly improve performance.
Additional thoughts:
I think you can clean up your code further.
IModuleCatalog mm = this.UnityContainer.Resolve<IModuleCatalog>();
foreach (var module in mm.Modules)
{
could be refactored to remove the reference to UnityContainer. In addition, IModuleCatalog would be instantiated via a wrapper around the List<Module> I mentioned in my reply to Problem 1. In other words, the IModuleCatalog would be a dynamic view of all loaded modules. I am assuming there is still more performance that can be pulled out of this design, but at least you are no longer dependent on Unity. That will help you better refactor your code later on for more performance gains.

Related

Silverlight MP3 Playing Library

I'm trying to play MP3 files in SilverSprite, and it's super buggy. Is there an alternative library I can use to play MP3s in Silverlight?
Edit: Now that there's a bounty, I'm specifically looking for something that:
Works with SL 3-4
Is a separate project/DLL
Will work in SilverSprite projects (I'm using a layer on top of SS) -- no GUI, just methods I can call to play sounds
Works with content that has the build action set to Content. I cannot use embedded resources due to a bug in SilverSprite. My app will not run.
Plays MP3s.
Can play multiple audio files at the same time
I hope it's clear what I'm trying to find. I would like something I can embed in my own game engine, which sits on top of SilverSprite. I will supply all the audio files in the XAP. (The SilverSprite audio is quite broken and doesn't work.)
Update: The specific direction I would probably like to go in is to instantiate a new MediaElement, set the source, and play it. I have some code below, but a) NaturalDuration.TimeSpan.TotalMilliseconds reports 0, and b) the .MediaOpened never triggers.
MediaElement m = new MediaElement();
m.Source = new Uri("Content/Audio/chimes.mp3", UriKind.Relative);
m.Stop(); // useless?
//m.SetSource(new FileStream("Content/Audio/chimes.mp3", FileMode.Open)); // "Permission denied" exception, is it even finding the file?
m.Volume = 1; // Max
m.Position = TimeSpan.FromMilliseconds(0);
while (m.CurrentState != System.Windows.Media.MediaElementState.Closed)
{
Thread.Sleep(10);
}
m.MediaOpened += (sender, e) =>
{
m.Play();
};
m.Play();
For some working code rather similar to your updated approach see http://www.wiredprairie.us/blog/index.php/archives/577 . Beware that the MediaElement needs to be added to the control/component tree - see http://www.michaelsnow.com/2010/12/17/playing-sound-effects-on-windows-phone-7/.
Two very interesting options for your requirements is this library and this one.
For this kind of stuff you could also implement/use a custom MediaStreamSource like this one... see here and here.
EDIT - some other options:
Playing multiple sounds in parallel via XNA see source code at http://create.msdn.com/en-US/education/catalog/sample/silverlightsound
Using MediaPlayer class from XNA 4 for example:
MediaPlayer.Stop();
MediaPlayer.Volume = 1;
MediaPlayer.Play(Song.FromUri("TestSound", new Uri("/Content/Audio/chimes.mp3", UriKind.Relative)));
As for playing multiple sound files at the same time:
IIRC this is something which could cause your app to fail validation.

WPF FormattedText "The system cannot find the file specified" exception in a service

We are using the WPF FormattedText object to determine text size in a service that grabs the latest news headlines from an RSS feed. The text retrieved needs to be in a specified canvas size. The service runs the code every 10 seconds and uses up to 2 threads if one takes longer than that. I'm using TaskFactory (which I've overridden the LimitedConcurrencyLevelTaskScheduler to limit to the amount of threads I specified).
This works great, except after several days (the length is variable), we start to get the following exceptions. The same code was working fine before we started using TPL to make it mult-threaded.
I need help figuring out what this is caused by. A few thoughts I'm looking into are: thread collisions holding on to a TTF file, memory issue, the dispatcher (see the stack trace) isn't playing nicely with the TaskFactory, other??
We don't have good profiling setup, but we've looked at the TaskManager when the exception is occurring and memory usage looks normal.
My next attempt is to use the TextBlock object and see if the exception is avoided.
Error Message: The system cannot find the file specified
Error Source: WindowsBase
Error Target Site: UInt16 RegisterClassEx(WNDCLASSEX_D)
Exception Stack Trace:
at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d)
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at System.Windows.Threading.Dispatcher..ctor()
at System.Windows.Threading.Dispatcher.get_CurrentDispatcher()
at System.Windows.Media.TextFormatting.TextFormatter.FromCurrentDispatcher(TextFormattingMode textFormattingMode)
at System.Windows.Media.FormattedText.LineEnumerator..ctor(FormattedText text)
at System.Windows.Media.FormattedText.DrawAndCalculateMetrics(DrawingContext dc, Point drawingOffset, Boolean getBlackBoxMetrics)
at System.Windows.Media.FormattedText.get_Metrics()
at
(my method using the FormattedText, which is in a loop)
private static Size GetTextSize(string txt, Typeface tf, int size)
{
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}
EDIT: so far I've tried placing a lock around the code that calls this function, and calling it inside the CurrentDispatcher.Invoke method like so:
return (Size)Dispatcher.CurrentDispatcher.Invoke(new Func<Size>(() =>
{
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}));
EDIT: I've found links to others having similar, but not the exact problem.
http://www.eggheadcafe.com/software/aspnet/31783898/problem-creating-an-bitmapsource-from-an-hbitmap-in-threaded-code.aspx ~having a similar problem, but no answers
System.Windows.Media.DrawingVisual.RenderOpen() erroring after a time ~having a similar problem, but no answers
http://connect.microsoft.com/VisualStudio/feedback/details/361469/net-3-5-sp1-breaks-use-of-wpf-under-iis# ~ similar exception, but we're not using 3.5SP1 or IIS 7.
I've also submitted this through the Microsoft Connect site (please vote for it if you are having a similar problem).
https://connect.microsoft.com/WPF/feedback/details/654208/wpf-formattedtext-the-system-cannot-find-the-file-specified-exception-in-a-service
EDIT: Response from Microsoft:
"WPF objects need to be created on Dispatcher threads, not thread-pool threads. We usually recommend dedicating a thread to run the dispatcher loop to service requests to create objects and return
them frozen. Thanks, WPF Team" ~ How would I implement this?
EDIT: final solution thanks to NightDweller
if(Application.Current == null) new Application();
(Size)Application.Current.Dispatcher.CurrentDispatcher.Invoke(new Func<Size>(() =>
{
...});
EDIT: When I deployed the change (new Application();), I got an error logged " Cannot create more than one System.Windows.Application instance in the same AppDomain."
Error Source: PresentationFramework
Error Target Site: Void .ctor()
A shot in the dark:
The stack trace seems to show that WPF does not find a Dispatcher in the thread executing GetTextSize, so it has to create a new one, which involves creating a handle to a window.
Calling this every 10 seconds means 8'640 threads, thus windows per day. According to Mark Russinovich, there is a limit of 32 K windows per session, which may explain the error in RegisterClassEx.
An idea to overcome this is to read the current dispatcher from your main thread and set it in your tasks.
Edit:
I had another look and it looks like one cannot set the Dispatcher of a thread (it's created automatically).
I'm sorry, I am unable to understand what is going on here.
In order to compute the text size, WPF needs a FormattedText instance, which is stored as a member of the Dispatcher class. The existing Dispatchers are stored in a list of weak references. Each one is associated with a specific thread.
Here, it looks like new Dispatcher instances are created many, many times.
So, either the calling thread is new or memory is quite low and the weak references have been discarded.
The first case (new thread) is unlikely as the task scheduler uses the thread pool, which has about 25 threads per core (if I remember correctly), which is not enough to deplete the pool of ATOMs or windows.
In the second case, the depletion of resource is unlikely as the HwndWrapper is IDisposable and the Dispose method takes care of freeing the registered class.
As you already know from the info you provided, All UI elements (FormattedText is one) have to be created on the UI thread.
The code you are looking for is:
return (Size)Application.Current.Dispatcher.CurrentDispatcher.Invoke(new Func<Size>(() =>
{
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}));
Notice the Application.Current - you want the "Application" dispatcher which is the dispatcher for the UI thread in WPF applications.
Your current code actually creates a dispatcher for the current thread so you didn't really change the executing thread (see here regarding the dispatcher)
Have you renamed anything? If yes, check that link: WPF Prism: Problem with creating a Shell

Windows Phone 7 App Quits when I attempt to deserialize JSON

I'm developing my first windows phone 7 app, and I've hit a snag. basically it's just reading a json string of events and binding that to a list (using the list app starting point)
public void Load()
{
// form the URI
UriBuilder uri = new UriBuilder("http://mysite.com/events.json");
WebClient proxy = new WebClient();
proxy.OpenReadCompleted += new OpenReadCompletedEventHandler(OnReadCompleted);
proxy.OpenReadAsync(uri.Uri);
}
void OnReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
var serializer = new DataContractJsonSerializer(typeof(EventList));
var events = (EventList)serializer.ReadObject(e.Result);
foreach (var ev in events)
{
Items.Add(ev);
}
}
}
public ObservableCollection<EventDetails> Items { get; private set; }
EventDetails is my class that wraps the json string. this class has to be correct because it is an exact copy of the class used by that website internally from which the json is generated...
I get the json string correctly from the webclient call (I read the memorystream and the json is indeed there) but as soon as I attempt to deserialize the string, the application exits and the debugger stops.
I get no error message or any indication that anything happen, it just stops. This happens if I type the deserialize method into the watch window as well...
I have already tried using JSON.net in fact I thought maybe it was a problem with JSON.net so I converted it to use the native deserializer in the .net framework but the error is the same either way.
why would the application just quit? shouldn't it give me SOME kind of error message?
what could I be doing wrong?
many thanks!
Firstly, the fact that you have some string there that looks like JSON does not mean that you have a valid JSON. Try converting a simple one.
If your JSON is valid, it might be that your JSON implementation does not know how to convert a list to EventList. Give it a try with ArrayList instead and let me know.
The application closes because an unhandled exception happens. If check the App.xaml.cs file you will find the code that closes your app. What you need to do is try catch your deserialization process and handle it locally. So most likely you have some JSON the DataContractJsonSerializer does not like. I have been having issue with it deserializing WCF JSON and have had to go other routes.
You may want to check to ensure your JSON is valid, just because your website likes it does not mean it is actually valid, the code on your site may be helping to correct the issue. Drop a copy of your JSON object (the string) in http://jsonlint.com/ to see if it is valid or not. Crokford (the guy who created JSON) wrote this site to validate JSON, so I would rely on it more than your site ;) This little site has really helped me out of some issues over the past year.
I ran into this same kind of problem when trying to migrate some existing WM code to run on WP7. I believe that the WP7 app crashes whenever it loads an assembly (or class?) that references something that's not available in WP7. In my case, I think it was Assembly.Load or something in the System.IO namespace, related to file access via paths.
While your case might be something completely different, the symptoms were exactly the same.
The only thing I can recommend is to go through the JSON library and see if it's referencing base classes that are not allowed in WP7. Note that it doesn't even have to hit the line of code that's causing the issue - it'll crash as soon as it tries to hit the class that contains the bad reference.
If you can step into the JSON library, you can get a better idea of which class is causing the problem, because as soon as the code references it, the whole app will crash and the debugger will stop.

Test Function in MVC Project

So I want to test one of my Functions in my Web Project, but it's not actually connected to anything in the project yet (someone else is working on that part). The Function takes in an "ID" field, goes off and does some queries and gets some data, performs some calculations on it, and then writes a bunch of lines to a FileStream and returns that stream. I pretty much just want to test it by having it write the file to my own computer locally, and working with that file directory after the Function completes.
So my question is mainly:
1) How do I call this Function just for testing purposes so I can test all the queries/calculations/File writes, etc without it being connected to another part of the application just yet.
2) How can I change the 'Return fs' for the FileStream to write to my own computer locally to view the file that has been written.
Thanks guys!
To make your function testable you need to isolate all your dependencies and replace them in your test with stubs mocks. You can achieve this by wrappers around the file system classes and making sure your data layers classes have interfaces. With this your code could look like:
public class Something
{
IDataProvider provider;
IFileSystem fileSystem;
public Something(IDataProvider provider, IFileSystem fileSystem)
{
this.provider = provider;
this.fileSystem = fileSystem;
}
void DoThing(int id)
{
// make database call to get data
var data = provider.GetData(id);
fileSystem.Write("someFilePath",data);
}
}
With this you can write a test as such (in this casing using Moq like syntax):
void SomeTest()
{
var mockDataProvider = new Mock<IDataProvider>();
var mockFileSystem = new Mock<IFileSystem>();
var something = new Something(mockDataProvider.Object, mockFileSystem.Object);
var data = "someData";
mockDataProvider.Setup(x => x.GetData(5)).Return(data);
DoThing(5);
mockFileSystem.Verify(x => x.Write("someFilePath",data);
}
You need to read up on Unit Testing as this solves your problem in so many ways - it would also introduce you to dependency injection and mocking, which would be a great way to handle your problem.
Here is an overview...
Set up your class so it accepts the data-access and file-writer in the constructor. You can then pass in mock or stub version of the data access and file writer so you don't physically need to connect to a database or write to the file system to test your code.
In the "real world" you pass in the genuine data access and file writer.
In "test world" you use something such as MOQ or Rhino Mocks to create a pretend version of the data access, this means you can predict what will come back from the data access every time you test as it isn't the real database, it's some data you have prepared. You can also create a pretend file-writer that doesn't actually need to write a real file.
You can then test your class in isolation.
Dependency Injection:
http://msdn.microsoft.com/en-us/magazine/cc163739.aspx
Moq
http://code.google.com/p/moq/

Will Prism OnDemand module loading work in an OOB scenerio?

Should the loading of OnDemand Prism modules work in an OOB scenerio? If so, I cannot seem to make it work. Everything is currently working in browser without any problems. Specifically I:
register my modules in code:
protected override IModuleCatalog GetModuleCatalog() {
var catalog = new ModuleCatalog();
Uri source;
if( Application.Current.IsRunningOutOfBrowser ) {
source = IsolatedStorageSettings.ApplicationSettings[SOURCEURI] as Uri;
}
else {
var src = Application.Current.Host.Source.ToString();
src = src.Substring( 0, src.LastIndexOf( '/' ) + 1 );
source = new Uri( src );
IsolatedStorageSettings.ApplicationSettings[SOURCEURI] = source;
IsolatedStorageSettings.ApplicationSettings.Save();
}
if( source != null ) {
var mod2 = new ModuleInfo { InitializationMode = InitializationMode.OnDemand,
ModuleName = ModuleNames.mod2,
ModuleType = "mod2.Module, mod2.Directory, '1.0.0.0', Culture=neutral, PublicKeyToken=null" ),
Ref = ( new Uri( source, "mod2.xap" )).AbsoluteUri };
catalog.AddModule( mod2 );
}
// per Jeremy Likeness - did not help.
Application.Current.RootVisual = new Grid();
return ( catalog );
}
later request for the module to be loaded is made:
mModuleManager.LoadModule( ModuleNames.mod2 );
and wait for a response to an event published during the initialization of that loaded module.
The module appears to never be loaded, and when the application is running under the debugger there will be a message box that states that the web server returned a 'not found' error. I can take the requesting url for the module and enter it into Firefox and download the module with no problem.
I have not been able to find any reference to this actually being workable, but it seems as though it should. The most I have found on the subject is a blog entry by Jeremy Likeness, which covers loading modules in MEF, but applying his knowledge here did not help.
The server is localhost (I have heard it mentioned that this might cause problems). The server has a clientaccesspolicy.xml file - although I don't expect that is needed.
I am using the client stack and register it during app construction:
WebRequest.RegisterPrefix( Current.Host.Source.GetComponents( UriComponents.SchemeAndServer, UriFormat.UriEscaped ), WebRequestCreator.ClientHttp );
Followup questions:
Can all of the xaps be installed to the client desktop in some manner - or only the main application xap? specify them in appmanifest.xml somehow??
Is it worth it make this work if only the application.xap is installed and the rest of the xaps must be downloaded anyway?
Once I worked on a similar scenario. The trick is having the modules stored in isolated storage and use a module loader that reads from isolated storage when working offline.
This is because otherwise, you can't get download the modules that are in a different .xap file than the Shell.
Thanks,
Damian
It is possible to hook custom module loaders into Prism if you're willing to tweak the Prism source and build it yourself. I was actually able to get this to work pretty easily - in our app, I look on disk first for the module, and if it's not found, I fall back to loading it from the server via a third-party commercial HTTP stack that supports client certificates.
To do this, download the Prism source code, and locate the Microsoft.Practices.Composite.Modularity.XapModuleTypeLoader class. This class uses another Prism class, Microsoft.Practices.Composite.Modularity.FileDownloader, to download the .xap content; but it instantiates it directly, giving you no chance to inject your own or whatever.
So - in XapModuleTypeLoader, I added a static property to set the type of the downloader:
public static Type DownloaderType { get; set; }
Then I modified the CreateDownloader() method to use the type specified above in preference to the default one:
protected virtual IFileDownloader CreateDownloader() {
if (_downloader == null) {
if (DownloaderType == null) {
_downloader = new FileDownloader();
} else {
_downloader = (IFileDownloader)Activator.CreateInstance(DownloaderType);
}
}
return _downloader;
}
When my app starts up, I set the property to my own downloader type:
XapModuleTypeLoader.DownloaderType = typeof(LocalFileDownloader);
Voila - now Prism calls your code to load its modules.
I can send you my LocalFileDownloader class as well as the class it falls back to to load the .xap from the web if you're interested... I suspect though that if you look at Prism's FileDownloader class you'll see that it's simple enough.
With regard to your other questions, the clientaccesspolicy.xml file is probably not needed if the URL the app is installed under is the same one you're talking to, or if you're in elevated trust.
The .xaps can definitely be pre-installed on the client, but it's a bit of work. What we did was write a launcher app that is a standalone .NET 2.0 desktop app. It downloads the main .xap plus certain modules* (checking for updates and downloading only as needed), then uninstalls/reinstalls the app if necessary, then launches the app. The last two are done via sllauncher.exe, which is installed as part of Silverlight. Here's a good intro to that: http://timheuer.com/blog/archive/2010/03/25/using-sllauncher-for-silent-install-silverlight-application.aspx.
Assuming you're running under elevated trust, it should also be possible to pre-fetch the module .xaps from within the SL client, but before they're actually requested due to user action. You'd just need to put them in a folder under My Documents somewhere, and then use the custom module loading approach described above to pull them from there.
*In our case, our main .xap is 2/3 of the application. The rest of our .xaps are small, so we download them on-the-fly, with the exception of some .xaps we created as containers for third-party components. We don't expect to update those very often, so we pre-install them.

Resources