8

現在のフレームワークの設計では、すべてのタイプの特定のアセンブリを熟読し、見つかったタイプに基づいて作業を行います。検索するアセンブリは、アプリケーションのブートストラッパー/イニシャライザーによって決定されます。アセンブリはコンパイルされるため、次の方法で強力に参照できますtypeof(SomeTypeInTheAssembly).Assembly。ブートストラッパーコードにはアセンブリ内の型への強い参照があり、アセンブリの修飾名が変更された場合に手動で最新の状態に保つ必要があるインライン文字列として完全修飾名をいじくり回す必要がないため、これは便利です。しかし、アセンブリ内で完全に無関係なタイプを参照し、そこにあるタイプに依存するのは好きではありませんでした。(別のアセンブリに移動した場合はどうなりますか?型を非推奨/削除した場合はどうなりますか?名前空間を変更しますか?)コードでは、少し奇妙に見えます:

FrameworkAssemblyReader.Read(typeof(SomeAssemblyNamespace.SubNamespace.GraphingCalculator).Assembly);

ブートストラップコードでは、直接依存関係があります(ただし、かなり些細な依存関係ですが)。GraphingCalculatorこれは、ブートストラップステージとは関係ありません(GraphingCalculatorとして、アセンブリ参照の取得とは関係ありません)。これを回避するために、このように使用する予定の各アセンブリで、ルートにクラスを追加しました。

namespace SomeAssemblyNamespace
{
    public static class AssemblyReference
    {
        public static System.Reflection.Assembly Get
        {
            get
            {
                return typeof(AssemblyReference).Assembly;
            }
        }
    }
}

私のブートストラップコードは次のようになっているので、それほど悪くはありません。

FrameworkAssemblyReader.Read(SomeAssembly.AssemblyReference.Get);

しかし、現在、このクラスをコピー/貼り付けしたアセンブリが約12ほどあり、AssemblyReferenceアプリケーションがフレームワーク上に構築されるにつれて、このクラスが成長し続けることを期待しています。だから私の質問は、AssemblyReferenceクラスの重複を避け、プログラムでベースフレームワークへのアセンブリ参照を渡し、それでもターゲットアセンブリ内の任意の/無関係なタイプを指すというあいまいさを避けるための良い方法はありますか?私のグーグルは、(クラスのように)アセンブリを強く指すことができるAPIまたは言語機能がないことを教えてくれますがtypeof、ここの誰かがクラス/コードを回避するより良い解決策を考え出したことを願っています複製。また、コードはSilverlightに対してコンパイルされることがあるため、API/手法の一部を制限する傾向があることもわかっています。ありがとう!

編集:「あらいくま」の答えに基づいて、別のモンキーレンチを追加するために、私は常に同じアセンブリをロードするとは限らないことに言及する必要があります。たとえば、すべてではないが一部のアプリケーションに適用できる「CarBuilding」アセンブリがあるとします。使用したいものを教えてくれるのはブートストラッパー次第です(開発者が採用しているカスタムのものと一緒に)

EDITx2:Jon Skeetの質問に答えるには:クライアント(または社内で)は、アプリケーションをサポートしたいプロジェクト/DLLを作成します。次に、これらのプロジェクトは内部ベースフレームワークを参照します。彼らのプロジェクトに、リソース(3Dファイル、画像、テキスト、ローカリゼーションなど)とプラグイン風のクラス(アプリケーションの存続期間中に必要に応じて検出およびインスタンス化/実行するスクリプトを実装する)が含まれる場合があります。さらに、私たちのシステムは、クライアント(または私たち)が特定のアプリケーションを作成するときに活用できる再利用可能なプラグイン/コンテンツを含むオプションのモジュール(DLL)を提供します。したがって、次のようなプロジェクト構造が表示される場合があります。

Solution
    ->MyAppBootstrapper_Android
        ->MyAppGUI_Android
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Android

    ->MyAppBootstrapper_Silverlight
        ->MyAppGUI_Silverlight
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Silverlight
        ->BaseFrameworkGraphingModule

ブートストラッパープロジェクトは依存関係を結び付け、検出のためにベースフレームワークに提供する必要があるプロジェクト/ dll(アセンブリ)を提供します。この場合、「MyApp」はAndroidビルドとSilverlightビルドの両方で独自のミニフレームワークと共有リソースを共有しますが、どちらも互いに独立した独自の参照を持っていることに注意してください。Silverlightは、を利用してBaseFrameworkGraphingModuleおり、プラットフォームに固有の独自のリソースを持っています。

したがって、プロジェクトのブートストラッパーでは、(単純化されていますが)次のようになります。

namespace MyAppBootstrapper_Android
{
    public class Bootstrapper
    {
        public void Setup()
        {
            FrameworkAssemblyReader.Read(MyAppGUI_Android.AssemblyReference.Get);
            FrameworkAssemblyReader.Read(MyAppFramework.AssemblyReference.Get);
            FrameworkAssemblyReader.Read(MyAppResources.AssemblyReference.Get);
            FrameworkAssemblyReader.Read(MyAppAdditionalResources_Android.AssemblyReference.Get);
        }
    }
}

namespace MyAppBootstrapper_Silverlight
{
    public class Bootstrapper
    {
        public void Setup()
        {
            FrameworkAssemblyReader.Read(MyAppGUI_Silverlight.AssemblyReference.Get);
            FrameworkAssemblyReader.Read(MyAppFramework.AssemblyReference.Get);
            FrameworkAssemblyReader.Read(MyAppResources.AssemblyReference.Get);
            FrameworkAssemblyReader.Read(MyAppAdditionalResources_Android.AssemblyReference.Get);
            FrameworkAssemblyReader.Read(BaseFrameworkGraphingModule.AssemblyReference.Get);
        }
    }
}

そのため、ベースフレームワーク上に構築されたアプリケーションごとに、含めるアセンブリ(およびその他の無関係な配線作業)を示すブートストラッパーが作成されます。具体的に質問に答えるために、プロジェクトには、ユーザーのスマートフォンまたはSilverlightアプリに動的にダウンロードされないため、必要な各アセンブリへのコンパイル時の参照があります(これにより、すべてのDLLがAndroid / Silverlight展開用に一緒にパッケージ化されるため、二重の義務が発生します)ただし、最初のダウンロードでパッケージ化されています。Bootstrappersがどのアセンブリを使用するかをどのように知っているかについてのあなたの質問は、開発者が必要なFrameworkAssemblyReader.Read呼び出しをよく知っており、発信します。これがお役に立てば幸いです。ご覧いただきありがとうございます。何もないところから作りすぎている(またははるかに優れたソリューション/設計を完全に見逃している)と感じています。

最後に、私は(ばかげて)、Mono for Android、そして近い将来、WPFに対してもコンパイルすることについて言及することを怠りました。WinRTは将来追加される可能性がありますが、私たちがそれに到達したときに、その橋を渡ることができれば幸いです。ただし、一般的には、それぞれが独自のプラットフォーム機能を使用して独自の方法でコンパイルされるため、プラットフォームごとにアセンブリ参照を取り込む方法が異なっていてもかまいません。プラットフォーム間に統一された構文があればいいのですが。

EDITx3:ええ、もう1つ。私は言及しましたが、すべてのプロジェクトが基本フレームワークによって読み取られる必要がある、または読み取られるべきではないことを例で明確にしませんでした。たとえば、基本フレームワークには関連しないがクライアントアプリケーションには関連するコードを持つユーティリティまたはビジネスロジックプロジェクト。したがって、上記の例から:

Solution
    ->MyAppBootstrapper_Android
        ->MyAppGUI_Android
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Android
        ->MyCompanySharedUtilities

    ->MyAppBootstrapper_Silverlight
        ->MyAppGUI_Silverlight
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Silverlight
        ->BaseFrameworkGraphingModule
        ->MyCompanySharedUtilities

MyCompanySharedUtilitiesMyAppGUI_SilverlightとMyAppFrameworkで活用できますがFrameworkAssemblyReader.Read、たとえば、数学やビジネスルールの独自の実装しか含まれていないため、開発者はそれを実行できない可能性があります。

4

1 に答える 1

4

クライアントがこのコードをどのように使用するかは正確にはわかりません。したがって、この提案は無関係かもしれませんが、セットアップ機能を廃止して(少なくともクライアントから非表示にして)使用する方が理にかなっています。ある種の設定ファイル?

<ReferencedAssemblies>
    <ReferencedAssembly key="UnchangingKey" qualifiedName="SomeAssemblyName, version=1.0.0.0, Culture=neutral, PublicKeyToken=0123456789abcdef" />
</ReferencedAssemblies>

構成ファイルからアセンブリをロードします。キーを使用すると、完全修飾名が変更された場合にアプリケーションを更新する必要はありません。構成ファイルを更新するだけです(キーはそのままにしておきます)。

これは、基本的に、VisualStudioがプロジェクトファイルで使用するアプローチです。これが私のVBプロジェクトの1つの例です:

<ItemGroup>
  <Reference Include="System.Core">
    <RequiredTargetFramework>3.5</RequiredTargetFramework>
  </Reference>
  <Reference Include="System.Drawing" />
  <Reference Include="System.Windows.Forms" />
  <Reference Include="System.Xml.Linq">
    <RequiredTargetFramework>3.5</RequiredTargetFramework>
  </Reference>
  <Reference Include="System.Data.DataSetExtensions">
    <RequiredTargetFramework>3.5</RequiredTargetFramework>
  </Reference>
  <Reference Include="UIAutomationProvider">
    <RequiredTargetFramework>3.0</RequiredTargetFramework>
  </Reference>
  <Reference Include="WindowsBase">
    <RequiredTargetFramework>3.0</RequiredTargetFramework>
  </Reference>
  <Reference Include="PresentationCore">
    <RequiredTargetFramework>3.0</RequiredTargetFramework>
  </Reference>
  <Reference Include="PresentationFramework">
    <RequiredTargetFramework>3.0</RequiredTargetFramework>
  </Reference>
  <Reference Include="System" />
  <Reference Include="System.Data" />
  <Reference Include="System.Xml" />
</ItemGroup>

編集:

これが考えです...Reflection.Emitを使用してXML構成ファイルからアセンブリを生成した場合はどうなりますか?生成されたアセンブリにスタブクラスを追加し、コアプロジェクトが生成されたアセンブリへのハード参照を作成するために使用できます。また、Reflectionを使用して(XMLファイル内の)各参照アセンブリをプローブし、任意のオブジェクトへのハード参照を作成できます。参照されるアセンブリ内。参照されているアセンブリの1つが変更されたときにアセンブリを再生成する必要がありますが、コードを変更する必要はありません。アセンブリ生成コードをコアプロジェクトに組み込んで、ユーザーが必要に応じてプロジェクトを更新できるようにすることもできます。

于 2012-07-03T13:34:59.117 に答える