C#Compact Framework 2.0アプリケーションのモジュール化
-
03-07-2019 - |
質問
現在、新しいハンドヘルドソフトウェアを開発しています。アプリケーションの性質については説明できないため、代わりに例を使用します。
学校を管理するためのハンドヘルドソフトウェアを設計しています。異なる学校が異なる機能を使用できるように、システムの各側面をモジュール化する必要があります。
システムは、メインメニューとログイン画面で起動します。これがシステムのベースになり、モジュールが追加される場所になりたいです。つまりSchoolPdaというプロジェクトがあります。
その後、異なるモジュールが必要です。つまり、学生の登録を処理する登録モジュールが必要です。教室の清潔さなどを管理するための教室モジュールが必要です。
この動作を確認する方法は、異なるdllを含めたり含めなかったり、dllが存在する場合にベースシステムのメインメニューにこれらのモジュールにアクセスするためのボタンを表示させることです。それは私たちが求めている種類のことです。
誰かこのようなことをした経験はありますか?それを行う最良の方法は何でしょうか?データベースは常に完全なデータベースであるため、データベースについて心配する必要はありませんが、関連するモジュールが存在しない場合はアスペクトにデータが取り込まれません。
解決
私はそれを2つの方法で行ったプロジェクトに参加しました:
-
あるプロジェクトでは、お客様がライセンスを取得していない場合、特定のDLLを展開しませんでした。それがあなたが提案していることです。うまくいきました。もちろん、追加のインストールを行わずにこれらのモジュールを有効にする方法はありませんでしたが、そのアプリには最適です。
-
別のプロジェクトでは、すべてを展開し、エンドユーザーに、顧客がライセンスされているメニュー、ボタンなどのみを公開しました。それは、ユーザーがライセンスを追加することで簡単に追加モジュールを追加できるためです。ライセンスが追加されると、次のログイン時にそれらが魔法のように表示されました。
したがって、私の経験では、ライセンスモデルを決定の大きな要素の1つと考えています。これらの追加モジュールをその場で追加したいかどうかを考えてください。
他のヒント
現在、コンパクトフレームワークとフルフレームワークの両方で実行され、モジュール式に構築されたアプリケーションも開発しています。
それを実装した方法は、dllの場所をスキャンし、各タイプを列挙し、それらが" ScreenInfoAttribute"を持っているかどうかを調べることです。または" WidgetInfoAttribute"クラスに関する有用な情報を含む定義済み。
ここにスニペットがあり、3.5のコードが含まれていますが、これは最近2.0から切り替えたためですが、原理は2.0で機能します
public void Analyze(FileInfo file) {
Assembly asm = Assembly.LoadFrom(file.FullName);
List<Data.AnyPlugin> types = GetPluginTypes(asm.GetTypes());
if (types.Count > 0) {
types.ForEach(x => x.AssemblyPath = file.FullName);
if (_plugins.ContainsKey(file.FullName)) {
_plugins[file.FullName].Plugins.AddRange(types);
} else {
AssemblyPlugin asp = new AssemblyPlugin();
asp.Ass = asm;
asp.Plugins = types;
_plugins.Add(file.FullName, asp);
}
}
}
private List<Data.AnyPlugin> GetPluginTypes(Type[] types) {
List<Data.AnyPlugin> returnTypes = new List<AnyPlugin>();
foreach (Type t in types) {
Data.AnyPlugin st = GetPluginType(t);
if (st != null) returnTypes.Add(st);
}
return returnTypes;
}
private Data.AnyPlugin GetPluginType(Type type) {
if (type.IsSubclassOf(typeof(Screens.bScreen<T>))) {
Screens.ScreenInfoAttribute s = GetScreenAttrib(type);
if (s != null) {
return new Data.ScreenPlugin("", type, s);
}
} else if (type.IsSubclassOf(typeof(Widgets.bWidget<T>))) {
Widgets.WidgetInfoAttribute w = GetWidgetAttrib(type);
if (w != null) return new Data.WidgetPlugin("", type, w);
}
return null;
}
private Screens.ScreenInfoAttribute GetScreenAttrib(Type t) {
Attribute a = Attribute.GetCustomAttribute(t, typeof(Screens.ScreenInfoAttribute));
return (Screens.ScreenInfoAttribute)a;
}
CLRで動作するかどうかはわかりませんが、 MEF をご覧ください、dll /モジュールを検出してロードする方法を作成します。モジュールにGetMenuItemメソッド(またはilkなど)を持たせて、必要な情報を取得して、メインメニューにボタンを追加できるようにすることもできます。
明らかに、メインメニューに別のデザインを使用するのが理にかなっていますが、コアを記述し、今後も新しいコンポーネントを記述し続けることができるように、モジュール化と拡張性の両方を実現する必要があります。コアを変更する必要はありません。
これがあまり意味をなさない場合は申し訳ありません。一方向にアイデアをお伝えしたいだけです。
すべてのモジュールに共通のインターフェースを実装させるだけです。 GetButtons()やGetActions()などのメソッドを追加します。
その後、AssemblyNameおよびClassNameに関する情報をconfig-ファイルに配置できます。 これで、指定されたAssemblyをロードし、Activator.CreateInstanceを使用してクラスのインスタンスを作成し、インターフェイスにキャストしてGetButtons()などのメソッドを呼び出すのが簡単になりました。