2010-09-09 5 views
6

Я знаю, что можно динамически загружать модули xap с использованием инфраструктуры Prism или MEF. Однако я бы не хотел использовать эти рамки; вместо этого загрузите мои файлы xap вручную. Итак, я создал следующий класс (адаптированный из Интернета):silverlight 4, динамически загружающие модули 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, однако, поскольку я загружаю его вручную, я устанавливаю «Копировать локальное = False». Но при выполнении следующий код бросает TypeLoadException:

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

Кажется, код не может найти класс InvoiceView. Но я проверил, что метод initXap() XapLoader был успешно выполнен. Итак, почему код не может найти класс InvoiceView? Может кто-нибудь помочь мне с этой проблемой?

+0

Более простой способ сделать это - использовать Managed Extensibility Framework (MEF), встроенный в Silverlight 4, в дополнение к .NET 4. –

ответ

1

Это основано на ответе автоответчика ниже, а не на вопросе.

Если вы удалите проект/модуль, файлы выходных DLL/XAP повсюду. Если вы нажмете кнопку «показать все файлы», вы увидите некоторые эти выходные файлы вывода в своем clientbin, bin и obj папки связанных проектов.

alt text

Вы можете удалить их по отдельности из проекта, или, в случае сомнений, поиск всех BIN и OBJ (например, с помощью настольного исследователя) и удалить все эти папки. Папки BIN/CLIENTBIN/OBJ будут воссозданы по мере необходимости (это задание, которое должно было выполнить «чистый» вариант в Visual Studio!)

Надеюсь, это поможет.

+0

Я выбрал ваш ответ как правильный, однако я заметил, что меню Build-> Clean Visual Studio не помогло. Удаление папок bin/obj может помочь (я еще не сделал), я просто не хочу этого делать что в настоящее время то, что я делаю, - это изменить номер порта веб-сервера. Кстати, эта проблема возникает так часто, даже когда я ничего не переименовал. – synergetic

1

Хорошо, я нашел причину. Вышеприведенный код работает. После создания нового проекта silverlight (Sales.xap) мне удалось скомпилировать мое решение один раз. Затем я удалил класс App в Sales.xap и переименовал стандартный класс MainPage в SalesView. Однако независимо от того, сколько раз я компилирую свое решение, веб-сервер разработки Visual Studio загружал первую версию Sales.xap (откуда?), Поэтому мой код не смог найти SalesView. В моем проекте Asp.Net моего хоста я установил порт сервера разработки на другой номер порта, и проблема исчезла. Таким образом, проблема была связана с сервером разработки Visual Studio. По-видимому, он хранит скомпилированные файлы xap в некоторой временной папке и не всегда обновляет эти файлы xap при изменении исходного кода.

+0

У меня была такая же проблема, я использовал chrome - @Xds правильно ,Кажется, что проблемы связаны с хром-кэшированием файлов xap! Если вы откроете окно инкогнито для одного и того же URL-адреса, вы увидите последние изменения (поскольку инкогнито не кэширует). Кроме того, если вы используете IExplorer для одного и того же URL-адреса, он будет показывать последнее - он также не кэширует. Можно было бы надеяться, что Google Chrome не будет кэшировать xap так жестко. :( – DeeStackOverflow

0

Что мне делать, чтобы избежать подобных проблем при выполнении свеже скомпилирован Silverlight ясно кэш браузера, хром даже имеет четкий кэш SilverLight;)

0

это XAP явления Cache часто связано с Visual Studio встроенный веб-сервер (ASP.NET Development Server). Просто остановите появление этого сервера, и кеш будет очищен. Начните снова свой проект, и вызывается последняя сборка вашего xap.

Смежные вопросы