silverlight 4, dynamically loading xap modules
Asked Answered
D

4

6

I know that it is possible to load xap modules dynamically using Prism or MEF framework. However, I'd like not to use those frameworks; instead load my xap files manually. So, I created the following class (adapted from internet):

public class XapLoader
{
    public event XapLoadedEventHandler Completed;

    private string _xapName;

    public XapLoader(string xapName)
    {
        if (string.IsNullOrWhiteSpace(xapName))
            throw new ArgumentException("Invalid module name!");
        else
            _xapName = xapName;
    }

    public void Begin()
    {
        Uri uri = new Uri(_xapName, UriKind.Relative);
        if (uri != null)
        {
            WebClient wc = new WebClient();
            wc.OpenReadCompleted += onXapLoadingResponse;
            wc.OpenReadAsync(uri);
        }
    }

    private void onXapLoadingResponse(object sender, OpenReadCompletedEventArgs e)
    {
        if ((e.Error == null) && (e.Cancelled == false))
            initXap(e.Result);

        if (Completed != null)
        {
            XapLoadedEventArgs args = new XapLoadedEventArgs();
            args.Error = e.Error;
            args.Cancelled = e.Cancelled;
            Completed(this, args);
        }
    }

    private void initXap(Stream stream)
    {
        string appManifest = new StreamReader(Application.GetResourceStream(
        new StreamResourceInfo(stream, null), new Uri("AppManifest.xaml",
                                       UriKind.Relative)).Stream).ReadToEnd();

        XElement deploy = XDocument.Parse(appManifest).Root;

        List<XElement> parts = (from assemblyParts in deploy.Elements().Elements()
                                select assemblyParts).ToList();

        foreach (XElement xe in parts)
        {
            string source = xe.Attribute("Source").Value;
            AssemblyPart asmPart = new AssemblyPart();
            StreamResourceInfo streamInfo = Application.GetResourceStream(
                 new StreamResourceInfo(stream, "application/binary"), 
                 new Uri(source, UriKind.Relative));
            asmPart.Load(streamInfo.Stream);
        }
    }
}

public delegate void XapLoadedEventHandler(object sender, XapLoadedEventArgs e);

public class XapLoadedEventArgs : EventArgs
{
    public Exception Error { get; set; }

    public bool Cancelled { get; set; }
}

The above code works fine; I can load any xap the following way:

XapLoader xapLoader = new XapLoader("Sales.xap");
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed);
xapLoader.Begin();

Now, I have a UserControl called InvoiceView in the Sales.xap project, so I would like to instantiate the class. In the current project (Main.xap) I added reference to Sales.xap project, however, since I load it manually I set "Copy Local = False". But when executed, the following code throws TypeLoadException:

Sales.InvoiceView view = new Sales.InvoiceView();

It seems the code can't find InvoiceView class. But I checked that XapLoader's initXap() method was successfully executed. So why the code can't find InvoiceView class? Can someone help me with this problem?

Dollydolman answered 9/9, 2010 at 4:8 Comment(1)
An easier way to do this is to use the Managed Extensibility Framework (MEF) that is built into Silverlight 4, in addition to .NET 4.Somato
N
1

This is based on the asker's self-answer below, rather than the question.

If you delete a project/module the output DLLs/XAP files do hang around. If you click the "show all files" button you will see some these left-over output files in your clientbin, bin and obj folders of related projects.

alt text

You can delete them individually from the project, or, when in doubt, search for all BIN and OBJ (e.g. using desktop explorer) and delete all those folders. The BIN/CLIENTBIN/OBJ folders will be recreated when needed (this the job that the "clean" option in Visual Studio should have done!)

Hope this helps.

Normally answered 9/9, 2010 at 8:21 Comment(1)
I chose your answer as correct, however, I noticed that Visual Studio's Build->Clean menu didn't help. Deleting bin/obj folders may help (I didn't do yet), I just do not want to do that repetitively. So, currently what I'm doing is to change web server's port number. By the way, this problem happens so often, even when I renamed nothing.Dollydolman
D
1

Ok, I found the cause. The above code works. After creating a new silverlight project (Sales.xap) I happened to compile my solution once. Then I deleted App class in the Sales.xap and renamed default MainPage class to SalesView. However, no matter how many times I compile my solution, Visual Studio's development web server was loading the first version of Sales.xap (where from?), so my code couldn't find SalesView. In my host Asp.Net project I set development server's port to a different port number, and the problem gone. So the problem was with Visual Studio's development server. Apparently it is keeping compiled xap files in some temporary folder, and doesn't always update those xap files when source code changed.

Dollydolman answered 9/9, 2010 at 5:29 Comment(1)
I was having the same problem, I was using chrome - @Xds is right. The problems seems to be with chrome caching xap files big time ! If you open an incognito window for the same URL you will see the latest changes (since the incognito does not cache). Also, if you use IExplorer for the same url, it will show the latest - it does not cache either. One would hope that google chrome does not cache the xap so rigidly. :(Holstein
N
1

This is based on the asker's self-answer below, rather than the question.

If you delete a project/module the output DLLs/XAP files do hang around. If you click the "show all files" button you will see some these left-over output files in your clientbin, bin and obj folders of related projects.

alt text

You can delete them individually from the project, or, when in doubt, search for all BIN and OBJ (e.g. using desktop explorer) and delete all those folders. The BIN/CLIENTBIN/OBJ folders will be recreated when needed (this the job that the "clean" option in Visual Studio should have done!)

Hope this helps.

Normally answered 9/9, 2010 at 8:21 Comment(1)
I chose your answer as correct, however, I noticed that Visual Studio's Build->Clean menu didn't help. Deleting bin/obj folders may help (I didn't do yet), I just do not want to do that repetitively. So, currently what I'm doing is to change web server's port number. By the way, this problem happens so often, even when I renamed nothing.Dollydolman
W
0

What I do to avoid such problems when executing freshly compiled Silverlight is clear the browser cache, chrome even has a clear silverlight cache ;)

Witherspoon answered 21/9, 2010 at 11:0 Comment(0)
S
0

this XAP Cache phenomena is often due to the visual studio embedded web server (ASP.NET Development Server). Just stop the occurence of this server and the cache will be cleared. Start again your project and the latest build of your xap is called.

Subalpine answered 11/10, 2011 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.