silverlight 4, динамически загружаемые модули xap
Я знаю, что можно динамически загружать модули xap, используя Prism или MEF Framework. Однако я бы не хотел использовать эти рамки; вместо этого загрузите мои файлы 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; }
}
Приведенный выше код работает нормально; Я могу загрузить любой xap следующим образом:
XapLoader xapLoader = new XapLoader("Sales.xap");
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed);
xapLoader.Begin();
Теперь у меня есть UserControl с именем InvoiceView в проекте Sales.xap, поэтому я хотел бы создать экземпляр класса. В текущем проекте (Main.xap) я добавил ссылку на проект Sales.xap, однако, поскольку я загружаю его вручную, я установил "Copy Local = False". Но при выполнении следующий код генерирует исключение TypeLoadException:
Sales.InvoiceView view = new Sales.InvoiceView();
Кажется, код не может найти класс InvoiceView. Но я проверил, что метод initXap() XapLoader был успешно выполнен. Так почему же код не может найти класс InvoiceView? Может кто-нибудь помочь мне с этой проблемой?
4 ответа
Это основано на ответе на вопрос аскера ниже, а не на вопросе.
Если вы удаляете проект / модуль, выходные DLL-файлы /XAP-файлы остаются без изменений. Если вы нажмете кнопку "Показать все файлы", вы увидите некоторые из этих оставшихся выходных файлов в папках clientbin, bin и obj связанных проектов.
Вы можете удалить их по отдельности из проекта или, если сомневаетесь, найти все BIN и OBJ (например, с помощью Desktop Explorer) и удалить все эти папки. Папки BIN/CLIENTBIN/OBJ будут воссозданы при необходимости (это работа, которую должна была выполнить опция "clean" в Visual Studio!)
Надеюсь это поможет.
Хорошо, я нашел причину. Приведенный выше код работает. После создания нового проекта Silverlight (Sales.xap) я однажды скомпилировал свое решение. Затем я удалил класс App в Sales.xap и переименовал класс MainPage по умолчанию в SalesView. Однако, независимо от того, сколько раз я компилировал свое решение, веб-сервер разработки Visual Studio загружал первую версию Sales.xap (откуда?), Поэтому мой код не мог найти SalesView. В моем проекте Asp.Net хоста я установил порт сервера разработки на другой номер порта, и проблема исчезла. Таким образом, проблема была с сервером разработки Visual Studio. Очевидно, он хранит скомпилированные файлы xap в какой-то временной папке и не всегда обновляет эти файлы xap при изменении исходного кода.
То, что я делаю, чтобы избежать подобных проблем при выполнении только что скомпилированного Silverlight - это очистка кеша браузера, в chrome даже есть прозрачный кеш silverlight;)
Это явление XAP Cache часто происходит из-за встроенного веб-сервера visual studio (ASP.NET Development Server). Просто остановите вхождение этого сервера, и кеш будет очищен. Начните снова ваш проект и последняя сборка вашего xap называется.