2012-12-14 13 views
5

私は、プラグインベースのシステムに似たデスクトップアプリケーションを開発しています。私は、 'Machine'オブジェクトを含むDLLをロードするクライアントモジュールを持っています。その後、 'Machine'オブジェクトは、明確に定義されたインタフェースごとに操作され、使用されます。オブジェクト間でデータを渡す#

「マシン」オブジェクトを含むDLLは、別のプログラムを使用してオンザフライで生成されるという難しい部分があります。 DLLを生成するアプリケーションは、ユーザー入力を受け付け、クラスを生成します。これは、ユーザーが指定したフィールドを含むC#コードファイルであり、そのクラスはDLLにコンパイルされます。 dllファイル)。

クライアントプログラムがこのDLLを取得し、動的にロードしてからこのマシンのオブジェクトで動作させます。

私はMachineオブジェクトとClientプログラムの間でデータを渡す問題を解決するソリューションをモデリングするのに苦労しています。なぜなら、マシンオブジェクトにどのデータが含まれているのかわからないからです。

クライアントプログラムは、次のことを実行します。

- dllを読み込み、 'machine'オブジェクトをインスタンス化します。 - 'machine'オブジェクトの一連の関数を呼び出します。これらは、インターフェイス経由でクライアントに知られています。 - 'machine'オブジェクトからさまざまな変数を抽出し、ユーザーに表示します。

私は最後のステップを実行できません。

注:フィールドに関するメタデータがDLL生成プログラムによって生成され、xmlファイルに格納される簡単なソリューションをプログラミングしました。クライアントプログラムは、これらのxmlファイルを使用して、マシンオブジェクトに格納されているフィールドに関する情報を取得します。次に、機械オブジェクトの反射を使用して、オブジェクトのフィールドにアクセスします。

私はこれが面倒で遅いと感じます。このようなものにパターンやメソッドがありますか?

+0

Managed Extensibility Framework(MEF)を見ましたか? http://mef.codeplex.com/ http://msdn.microsoft.com/en-us/library/dd460648.aspx – spender

+0

私はそれについて聞いたことがあり、その使い方の簡単なアイデアがあります。私はプログラミングに慣れていないので、他の言語やシステムに容易に移植できるソリューションを実装したいと考えています。また、私は実際にこれらの複雑なシステムを実装することを学びたいと思います。 –

+0

C#で実装することで、Linuxや他のプラットフォーム上で動作する.NetフレームワークのポートであるMonoが存在するため、他のシステムに移植することができます。私はそれを他の言語にすばやく移植することは一般的だが、必ずしも心配する必要はない。それぞれの言語とプラットフォームには、独自のイディオムとベストプラクティスがあり、その中でうまくいくものは別の言語でうまく機能しないことがあります。 –

答えて

3

ソリューションが含まれ、クライアントのすべての種類を持っていますこれはC#でAttributesのビルトインサポートを利用することでした。属性は、例えば、Serializationの間に、他のいくつかのクラスによって使用されるいくつかの追加のメタデータでプロパティ、フィールド、メソッド、クラスなどをタグ付けする方法です。あなたはそれを最も頻繁に見ます。

私は、オブジェクトのコレクションIEnumerableを取得し、ユーザーが選択した選択肢に基づいてファイルにデータを出力できるようにするために必要なアプリケーションを作成しました。私は、リフレクションによって選択肢を読んで、指示どおりに行動する能力を与えた属性クラスを作成しました。私はあなたに例を示しましょう:

まず属性クラス:上迷子にしないよう

[System.AttributeUsage(AttributeTargets.Property)] 
class ExportOptionsAttribute : System.Attribute 
{ 
    public string Header { get; set; } 
    public string FormatString { get; set; } 
    public bool Export { get; set; } 
    public int Order { get; set; } 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="header"></param> 
    public ExportOptionsAttribute(string header) : this (header, null, true) 
    { 

    } 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="header"></param> 
    /// <param name="formatString"></param> 
    /// <param name="export"></param> 
    public ExportOptionsAttribute(string header, string formatString, bool export) 
    { 
     this.Header = header; 
     this.FormatString = formatString; 
     this.Export = export; 
     this.Order = 0; 
    } 
} 

以下の様に定義された、このクラスでは、私はこのように私のデータクラスのプロパティを飾ることができ(実際の性質はそう変更しましたビジネス専門用語):私の輸出ルーチンでそれでは

public sealed class PartsOrder 
{ 
    /// <summary> 
    /// 
    /// </summary> 
    [ExportOptions("Customer Name", Order=0)] 
    public string CustomerName { get; set; } 

    /// <summary> 
    /// 
    /// </summary> 
    [ExportOptions("Catalog Name", Order = 1)] 
    public string Catalog Name { get; set; } 

    /// <summary> 
    /// 
    /// </summary> 
    [ExportOptions("Unit", Order = 2)] 
    public string Unit { get; set; } 

    /// <summary> 
    /// 
    /// </summary> 
    [ExportOptions("Component", Order = 3)] 
    public string Component { get; set; } 

    /// <summary> 
    /// 
    /// </summary> 
    [ExportOptions("Delivery Point", Order = 4)] 
    public string DeliveryPoint { get; set; } 

    /// <summary> 
    /// 
    /// </summary> 
    [ExportOptions("Order Date", Order = 5)] 
    public string OrderDate { get; set; } 
} 

、代わりにハードコーディング可変であるプロパティ名を、あるいは表示または非表示にするフィールドの情報が含まれているの周りに複雑なデータ構造を渡します注文とは何ですか、私は反射を使用してプロパティをループし、その値をCSVファイルに出力する次のコードを実行しただけです。

StringBuilder outputDoc = new StringBuilder(); 

// loop through the headers in the attributes 
// a struct which decomposes the information gleaned from the attributes 
List<OrderedProperties> orderedProperties = new List<OrderedProperties>(); 

// get the properties for my object 
PropertyInfo[] props = 
    (typeof(PartsOrder)).GetProperties(); 

// loop the properties 
foreach (PropertyInfo prop in props) 
{ 
    // check for a custom attribute 
    if (prop.GetCustomAttributesData().Count() > 0) 
    { 
     foreach (object o in prop.GetCustomAttributes(false)) 
     { 
      ExportOptionsAttribute exoa = o as ExportOptionsAttribute; 

      if (exoa != null) 
      { 
       orderedProperties.Add(new OrderedProperties() { OrderByValue = exoa.Order, PropertyName = prop.Name, Header = exoa.Header, Export = exoa.Export }); 
      } 
     } 
    } 
} 

orderedProperties = orderedProperties.Where(op => op.Export == true).OrderBy(op => op.OrderByValue).ThenBy(op => op.PropertyName).ToList(); 

foreach (var a in orderedProperties) 
{ 
    outputDoc.AppendFormat("{0},", a.Header); 
} 

// remove the trailing commma and append a new line 
outputDoc.Remove(outputDoc.Length - 1, 1); 
outputDoc.AppendFormat("\n"); 


var PartsOrderType = typeof(PartsOrder); 

//TODO: loop rows 
foreach (PartsOrder price in this.Orders) 
{ 
    foreach (OrderedProperties op in orderedProperties) 
    { 
     // invokes the property on the object without knowing the name of the property 
     outputDoc.AppendFormat("{0},", PartsOrderType.InvokeMember(op.PropertyName, BindingFlags.GetProperty, null, price, null)); 
    } 

    // remove the trailing comma and append a new line 
    outputDoc.Remove(outputDoc.Length - 1, 1); 
    outputDoc.AppendFormat("\n"); 
} 

OrderedProperties構造体のためのコードはここにある:

struct OrderedProperties 
{ 
    /// <summary> 
    /// 
    /// </summary> 
    public int OrderByValue; 
    /// <summary> 
    /// 
    /// </summary> 
    public string PropertyName; 
    /// <summary> 
    /// 
    /// </summary> 
    public string Header; 
    /// <summary> 
    /// 
    /// </summary> 
    public bool Export; 
} 

あなたが見ることができるように、プロパティの値を抽出するロジックは、クラスの構造を完全に無知です。それは、私が作成した属性で装飾されたプロパティを見つけ出し、それを使って処理を駆動するだけです。

私はこれがすべて意味があることを願っており、さらに助けや説明が必要な場合はお気軽にお問い合わせください。

+0

あなたに送信されるオブジェクトのプロパティがわからずにコードを生成しています。私のプログラムであなたのソリューションを使用するには、コード生成モジュールを変更して、これらの属性を.csファイルに含めて、その場で生成していなければなりません。私は今これを実装します。ありがとう。しかし、もっと低レベルの方法で同じことをする他の方法も知っていますか?私がやっていることをコンパイラがやっているのではなく、もう少し本質的には?私はそれも反射を使用しているとは思わない。私は正しい? –

+1

はい、それは正しいでしょう。しかし、トレードオフは、あなたの側ではるかに簡単な処理セットです。属性は、フィールドやメソッドのスタック可能なメタデータと考えることができます。あなたが期待する属性を知っている限り、データの整理を行い、返された実際のオブジェクトについてほとんど知りません。 [また、属性の値は実行時に必要に応じて設定することができます。](http://stackoverflow.com/questions/51269/change-attributes-parameter-at-runtime) –

+0

上記の実装方法をご存知ですか? c/C++のソリューション?または、あなたがやったことに関連するドキュメンテーションでしょうか?私はこれらの言語でのコーディングがより裸の骨レベルでの解決策の理解を本当に容易にするので、c/C++を主張しています。 –

2

軽量MQソフトウェアであるZeroMQを取得して、アプリケーション間の通信を有効にすることもできます。 ZeroMQには1つのdllだけが含まれており、任意のアプリケーションに組み込むことができます。

ZeroMQは、私が読んだときに頭に来たC、C++、.NET、PythonやJavaの、ルビー、および両方のWindows/Linuxの/ OSXで実行することができます。..

+0

ZeroMQはWebアプリケーションに適していませんか?私のアプリケーションはデスクトップアプリケーションです。 –

+3

いいえ、アプリケーションには適していますが、ウェブには適していません。埋め込まれています。 –

+0

ソケットを使用しているように見えるのは、リフレクションを使用するのと同じくらいパフォーマンスが高くなります。 –

関連する問題