Je sais qu'il est possible de charger dynamiquement des modules xap en utilisant le framework Prism ou MEF. Cependant, j'aimerais ne pas utiliser ces cadres. au lieu de charger mes fichiers xap manuellement. Donc, j'ai créé la classe suivante (adaptée d'Internet):silverlight 4, chargement dynamique de modules 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; }
}
Le code ci-dessus fonctionne très bien; Je peux charger une XAP de la façon suivante:
XapLoader xapLoader = new XapLoader("Sales.xap");
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed);
xapLoader.Begin();
Maintenant, j'ai un UserControl appelé InvoiceView dans le projet Sales.xap, donc je voudrais instancier la classe. Dans le projet en cours (Main.xap) j'ai ajouté une référence au projet Sales.xap, cependant, puisque je le charge manuellement, je définis "Copy Local = False". Mais lorsqu'il est exécuté, le code suivant lance TypeLoadException:
Sales.InvoiceView view = new Sales.InvoiceView();
Il semble que le Code ne peut pas trouver la classe InvoiceView. Mais j'ai vérifié que la méthode initXap() de XapLoader était exécutée avec succès. Alors pourquoi le code ne peut pas trouver la classe InvoiceView? Quelqu'un peut-il m'aider avec ce problème?
Un moyen plus facile d'y parvenir est d'utiliser le MEF (Managed Extensibility Framework) intégré à Silverlight 4, en plus de .NET 4. –