So che è possibile caricare i moduli xap in modo dinamico utilizzando il framework Prism o MEF. Tuttavia, mi piacerebbe non usare questi framework; caricare invece i miei file xap manualmente. Così, ho creato la classe seguente (adattato da internet):silverlight 4, caricamento dinamico dei moduli xap
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; }
}
Il codice di cui sopra funziona bene; Posso caricare qualsiasi xap seguente modo:
XapLoader xapLoader = new XapLoader("Sales.xap");
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed);
xapLoader.Begin();
ora, ho un UserControl chiamato InvoiceView nel progetto Sales.xap, quindi vorrei creare un'istanza della classe. Nel progetto corrente (Main.xap) ho aggiunto un riferimento al progetto Sales.xap, tuttavia, poiché lo carico manualmente, imposto "Copy Local = False". Ma quando viene eseguito, il codice seguente getta TypeLoadException:
Sales.InvoiceView view = new Sales.InvoiceView();
Sembra che il codice non può trovare la classe InvoiceView. Ma ho controllato che il metodo initXap() di XapLoader fosse stato eseguito con successo. Quindi, perché il codice non riesce a trovare la classe InvoiceView? Qualcuno può aiutarmi con questo problema?
Un modo più semplice per farlo è utilizzare il Managed Extensibility Framework (MEF) incorporato in Silverlight 4, oltre a .NET 4. –