8

私のプロジェクトには、純粋なデータ指向アプリケーションであるServiceStack OrmLiteを選択しました。CodeDOMを使用して実行時にクラスを生成するために使用される XML 形式で定義された独自のオブジェクト型をエンド ユーザーが作成できるようにしたいと考えています。

アプリケーションに必要な「システム」オブジェクト (つまりUser) もいくつか定義しますが、エンド ユーザーが使用するすべてのプロパティを予測することはできないため、設計時に作成したクラスを拡張できる方法を探しています。以下のサンプル

public class User
{
    public Guid Uid { get; set; }
    public String Username { get; set; }
    public String Password { get; set; }
}

エンド ユーザーは と を必要としていEmailますAddress。彼は 2 つのプロパティを上位クラスに追加できるはずであり、クラス全体が追加されます (上書きが許可されているため、OrmLite で引き続き使用できます:

public class User
{
    public Guid Uid { get; set; }
    public String Username { get; set; }
    public String Password { get; set; }
    public String Email{ get; set; }
    public String Address { get; set; }
}

(クラスが既にインスタンス化されている場合) システムをクラッシュさせるリスクがあることを知っているので、この問題を回避し、必要性を模倣する最善の方法を探しています。

4

4 に答える 4

4

あなたがここでやっていることには 2 つの部分があるようです。追加のプロパティをサポートするには、型を動的に作成する必要があります。また、AppDomain で型が重複しないようにする必要もあります。つまり、 の 2 つの異なる定義ですUser

ランタイム型の生成

既に与えられたさまざまな提案は、型の作成方法を処理します。あるプロジェクトでは、似たようなことがありました。コア プロパティと「拡張」プロパティを格納するディクショナリを持つ基本クラスを作成しました。次にReflection.Emit、目的のプロパティを持つ派生型を作成していました。各プロパティ定義は、基本クラスのディクショナリから読み取ったり、ディクショナリに書き込んだりするだけです。Reflection.Emit低レベルの IL コードを記述する必要があるため、最初は複雑に見えます。サンプルの派生クラスを別のクラス ライブラリにいくつか作成し、コンパイルしました。これらは、実行時に実際に達成する必要があることの例です。次に、ildasm.exe を使用して、コンパイラが生成したコードを確認しました。これにより、実行時に同じコードを生成する方法を簡単に見つけることができました。

名前空間の衝突の回避

2 番目の課題は、型名が重複しないようにすることです。これが起こらないように、生成された各型の名前に (無効な文字を削除した) GUID を追加しました。簡単に修正できますが、ORM でそれを回避できるかどうかはわかりません。

これがサーバー コードの場合、.NET ではアセンブリがアンロードされないという事実も考慮する必要があります。したがって、実行時に新しい型を繰り返し生成している場合、プロセスは成長し続けます。クライアント コードでも同じことが起こりますが、プロセスが長時間実行されることが予想されない場合は、それほど問題にならない可能性があります。

アセンブリはアンロードされないと言いました。ただし、全体をアンロードできますAppDomain。したがって、これがサーバー コードである場合は、操作全体を独自の appdomain で実行し、後で破棄して、動的に作成された型が確実にアンロードされるようにすることができます。

于 2013-01-28T17:04:52.490 に答える
1

ExpandoObjectこのようなことを行うための動的言語サポートを提供する を確認してください。これを使用して、実行時に POCO に追加のプロパティを追加できます。.NET の DLR 機能の使用に関するリンクは次のとおりです: http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject%28v=vs.100%29.aspx

于 2013-01-27T00:08:20.237 に答える
0

私が現在取り組んでいるプロジェクトには、同様の要件があります。システムはすでに稼働しており、クライアントからフィールドの追加要求がありました。

モデルに CustomFields プロパティを追加するだけで、これを解決しました。

public class Model: IHasId<Guid>
{
    [PrimaryKey]
    [Index(Unique = true)]
    public Guid Id { get; set; }

    // Other Fields...

    /// <summary>  
    /// A store of extra fields not required by the data model.  
    /// </summary>  
    public Dictionary<string, object> CustomFields { get; set; }  
}

これを数週間問題なく使用しています。

これにより得られた追加の利点は、各行に独自のカスタム フィールドを設定できるため、すべてのレコードにカスタム フィールドを要求するのではなく、レコードごとに処理できることです。

于 2013-01-23T18:06:13.303 に答える
0

すべてのプロパティ、または少なくとも動的プロパティにキーと値のペアを使用しないのはなぜですか?

http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx

リフレクションで説明している方法で実行できますが、パフォーマンスが低下します。この方法では、プロパティも削除できます。

于 2013-01-20T00:28:11.790 に答える