6

Prism または MEF フレームワークを使用して xap モジュールを動的にロードできることを知っています。ただし、これらのフレームワークは使用したくありません。代わりに、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();

さて、Sales.xap プロジェクトに InvoiceView という UserControl があるので、このクラスをインスタンス化したいと思います。現在のプロジェクト (Main.xap) では、Sales.xap プロジェクトへの参照を追加しましたが、手動で読み込むため、"Copy Local = False" を設定しました。しかし、実行すると、次のコードは TypeLoadException をスローします。

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

コードが InvoiceView クラスを見つけられないようです。しかし、XapLoader の initXap() メソッドが正常に実行されることを確認しました。では、なぜコードは InvoiceView クラスを見つけられないのでしょうか? 誰かがこの問題で私を助けることができますか?

4

4 に答える 4

1

わかりました、原因がわかりました。上記のコードは機能します。新しい Silverlight プロジェクト (Sales.xap) を作成した後、たまたまソリューションをコンパイルしました。次に、Sales.xap の App クラスを削除し、デフォルトの MainPage クラスの名前を SalesView に変更しました。しかし、何度ソリューションをコンパイルしても、Visual Studio の開発用 Web サーバーは Sales.xap の最初のバージョンをロードしていたため (どこから?)、私のコードは SalesView を見つけることができませんでした。私のホスト Asp.Net プロジェクトでは、開発サーバーのポートを別のポート番号に設定しましたが、問題は解決しました。したがって、問題は Visual Studio の開発サーバーにありました。どうやら、コンパイルされた xap ファイルを一時フォルダーに保持しているようで、ソース コードが変更されたときにそれらの xap ファイルを常に更新するとは限りません。

于 2010-09-09T05:29:51.880 に答える
1

これは、質問ではなく、以下の質問者の自己回答に基づいています。

プロジェクト/モジュールを削除すると、出力 DLL/XAP ファイルが残ります。[すべてのファイルを表示] ボタンをクリックすると、関連プロジェクトのclientbinbin、およびobjフォルダーに、これらの残りの出力ファイルがいくつか表示されます。

代替テキスト

それらをプロジェクトから個別に削除するか、疑わしい場合は、すべての BIN と OBJ を検索して (たとえば、デスクトップ エクスプローラーを使用して)、それらのフォルダーをすべて削除します。BIN/CLIENTBIN/OBJ フォルダーは、必要に応じて再作成されます (これは、Visual Studio の「クリーン」オプションで行うべき作業です!)

お役に立てれば。

于 2010-09-09T08:21:43.563 に答える
0

この XAP キャッシュ現象は、多くの場合、Visual Studio に組み込まれた Web サーバー (ASP.NET 開発サーバー) が原因です。このサーバーの発生を停止するだけで、キャッシュがクリアされます。プロジェクトを再開すると、xap の最新ビルドが呼び出されます。

于 2011-10-11T13:18:01.480 に答える
0

新しくコンパイルされたSilverlightを実行するときにこのような問題を回避するために私がすることは、ブラウザのキャッシュをクリアすることです.chromeにはクリアなSilverlightキャッシュもあります;)

于 2010-09-21T11:00:23.760 に答える