4

不変にしたい次のC#クラスがあるとしましょう。パラメータ化されたコンストラクタを使用してのみ設定できます。

public class InsulineInjection
{
    private InsulineInjection()
    {
        // We don't want to enable a default constructor.
    }

    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
    {
        this.Remark = remark;
        this.DateTime = dateTime;
        this.Millilitre = millilitre;
    }

    public string Remark { get; private set; }
    public DateTime DateTime { get; private set; }
    public Millilitre Millilitre { get; private set; }
}

ここで、ORMを使用してこのPOCOを作成したいと思います。ただし、私が見る限り、すべての.NET ORMは、プロパティがアクセス可能であり、このPOCOを作成できるパブリックコンストラクターを持っていることを期待しています。だから私は私のPOCOをこれに変更する必要があります:

public class InsulineInjection
{
    public InsulineInjection()
    {
    }

    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
    {
        this.Remark = remark;
        this.DateTime = dateTime;
        this.Millilitre = millilitre;
    }

    public string Remark { get; set; }
    public DateTime DateTime { get; set; }
    public Millilitre Millilitre { get; set; }
}

ただし、これにより、POCOが再び変更可能になります。それを使用している人は、後でプロパティを変更するだけで、私が望むものではありません。

私が見る限り、これは2つの異なる方法で解決できます。

  1. 作成したコンストラクターを使用して正しいPOCOインスタンスを作成できるように、独自のデータアクセスレイヤーを作成します(またはormを変更します)。
  2. ある種のマッパーを作成します。ORMに単純なDTOオブジェクトを作成させ、マッパーを使用して適切なタイミングでDTOオブジェクトをPOCOに変換します。

私は解決策2に傾いています。誰かがこれを行う方法の例を持っていますか?または、誰かが私が上で説明したものよりも優れた解決策を持っていますか?

4

4 に答える 4

5

多くのOR/Mは、デフォルトのコンストラクターとセッターが存在する限り機能します(パブリックであるかどうかに関係なく、存在する必要があります)。

したがって、これは機能しません(デフォルトのコンストラクターはありません):

public class InsulineInjection
{
    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
    {
        this.Remark = remark;
        this.DateTime = dateTime;
        _millilitre = millilitre;
    }

    public string Remark { get; set; }
    public DateTime DateTime { get; set; }
    public Millilitre Millilitre { get { return _millilitre; } }
}

またはこれ(最後のプロパティのセッターなし)

public class InsulineInjection
{
    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
    {
        this.Remark = remark;
        this.DateTime = dateTime;
        _millilitre = millilitre;
    }

    public string Remark { get; set; }
    public DateTime DateTime { get; set; }
    public Millilitre Millilitre { get { return _millilitre; } }
}

これは機能しますが:

public class InsulineInjection
{
    protected InsulineInjection()
    {
        // works with many OR/Ms
    }

    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
    {
        this.Remark = remark;
        this.DateTime = dateTime;
        this.Millilitre = millilitre;
    }

    public string Remark { get; private set; }
    public DateTime DateTime { get; private set; }
    public Millilitre Millilitre { get; private set; }
}
于 2012-11-09T14:36:28.927 に答える
3

コンストラクターが独自のコードで使用されるのを避けるために、Obsolete属性を使用できます

[Obsolete("Default constructor only here for the ORM", true)]
public InsulineInjection() {}

このコンストラクターを実際に呼び出すと、属性を渡すtrueとコンパイラーエラーが発生します。

于 2012-11-09T14:36:13.550 に答える
2

すべての.NETORMが、データを書き込むためにパブリックプロパティへのアクセスを必要とするわけではありません。NHibernateは、プライベートフィールドまたはセッターへのデータの書き込みをサポートしています。ただし、プロパティ名からフィールド名を推測できるように、フィールドで許可されている命名規則の1つに従う必要があります。

プロパティマッピングに関するNHibernateのドキュメントを確認してください。特に、表5.1の表を参照してください。アクセス戦略と表5.2。ネーミング戦略。アクセス戦略を見てnosetter、コーディングスタイルに合った命名戦略を選択してください。

于 2012-11-09T14:36:05.680 に答える
1

このシナリオは、dapper-dot-netによってネイティブに処理されます。

コンストラクター引数の順序とタイプに一致するクエリフィールドの順序とタイプが必要です。したがって、クラスの場合、クエリは次のようになります。

select millilitre, 
    ,dateTime
    ,remark
from injections

残念ながら、dapperは何かを10進数からミリリットルに変換する方法を知りません。

于 2013-12-19T01:06:12.770 に答える