2017-01-06 5 views
0

一般的なタイプコンバータを作成しようとしています。すべてのタイプは基本クラスがEntity、インターフェイスがIConvertableです。私は変換することができ、オブジェクトのためのインタフェースを実装しました:Generic Typesで静的呼び出しを置き換える正しい構造体は何ですか?

public interface IConvertable 
{ 
    public bool CanConvert<TTarget>() where TTarget : Entity, IConvertable 
    Tuple<bool, Entity> TryConvertTo<TTarget> where TTarget: Entity, IConvertable 
} 

アイデアは、エンティティの各特定のサブクラスは(partialクラスは、自動生成されたコードは、私が直接変更することはできません)CanConvert<TTarget>を持っているということです、ターゲットタイプに変換できるかどうかを判断します。

私はそれらを変換する(そして、同時に他のタスクを実行する - 他のインタフェースを介して、たとえば、親を変更)、一緒にEntityIEnumerable秒かかりますジェネリック型コンバータを、入れしようとしていたし、その後Entity変換返しますクラス。

私の最初の実現は、それは常にからTSourceTTargetに一定であるという点で効果的に、CanConvert<TTarget>は、staticである、ということでしたので、私は私のコンバータビルドするとき:明らか

public class EntityConverter<TSource, TTarget> where TSource : Entity, IConvertable 
               where TTarget : Entity, IConvertable 
{ 
    private IEnumerable<TSource> Records { get; set; } 

    public EntityConverter(IEnumerable<TSource> records) { 
     if (!TSource.CanConvert<TTarget>()) { 
      // error condition, reporting, etc. 
     } 

     Add(records); 
    } 

    public void Add(IEnumerable<TSource> records) { ... } 

    public void Convert() { 
     // massively simplified for example - there will actually be a store 
     // holding, more functionality, parent-child relationships, but 
     // this is the basic principle 
     for (var c in convertables) { 
      c.TryConvertTo<TTarget>(); 
     } 
    } 
} 

を、多くの理由がありますstatic関数をジェネリックで使用することはできません(Eric Lippertsの優秀な説明はonhisblogです)しかし、これは私を過酷な状態に陥ります。タイプ(Not Instance)を記述し、タイプ、一般的な構造で、大規模な外部partial構造体または悪質なファクトリ - これは、インターフェイス実装で単にpartial型を拡張することによって、誰かが別のクラスから呼び出すことができる、拡張可能で再利用可能な構造体であると考えられています。

私は物事を間違った方向に見ていると思われますが、何が見えないのでしょうか。どのようにタイプ変換が有効かどうかを判断するには、中間にタイプ変換を保持する必要はありませんか?

edit コードサンプルを少し前に更新しました(以前はコンストラクタで変換されていました)。実際に変換する前に、コンバート可能な複数のソースを追加する必要があるため、実際にはこのプロセスでかなり後で変換を行います。この結果、実際のエラー(If !CanConvert<TTarget>())がかなり下がってしまいます。このクラスの各インスタンス化では、タイプTSourceからTTargetへの変換が行われるため、コンバーターの有効性をコンストラクターに知らせる必要があります。後で変換するのではなく、コンストラクターでエラーが発生します。少なくともそれは物事についての私の読書です。

私の考えを明確にしてくれたおかげで...とにかくこれを再構築することになるかもしれませんが、私は遠く離れているとは感じません。私はのチェックをAdd()の機能の中に入れようと考えていました...私はそこにいるように感じます...

+1

'convertables'の各インスタンスで' CanConvert'を呼び出すだけで何が問題になりますか? 'TBase'は' TSerething'に変換できないかもしれないので、 'TDerived:TBase'は' TBase'です。 –

+1

サイドノート:タプルは使用しないでください。 'bool TryConvertTo (エンティティの結果)'はより良いデザインです –

+1

また、 'convertables'をコンストラクタに渡すことが最良の方法であるとは確信していません。それはおそらく方法であるべきです。そして、他の操作(「実際には店舗 //持ち、より多くの機能があります」)は、「EntityConverter」によるhttps://en.wikipedia.org/wiki/Single_responsibility_principleの違反の可能性を示唆しています。コンバータは変換する必要があります - その名前が示すものです。 –

答えて

1

私の視点からは、AutoMapperのための作業のように思えます。オブジェクトから他のプロパティにプロパティを設定する必要があります。それで全部です。

私はあなたが数日または数ヶ月でAutoMapperが何をしているのか分かりません。

私はこれがあなたの質問に全く答えないことを理解していますが、私はそれがあなたのものをオーバーエンジニアリングするのではなく、良い解決策を見つけることだと感じています。

+0

ありがとうございました。私はAutomapperを見てきました。変換プロセスに必要なものの95%を占めるようです。残りは私自身のコードで行うことができます。あなたが言うように、問題の良い解決策を見つけることは、それが尋ねられたものではなくても、働くが、最適ではない、あるいは維持するのが難しい解決策を強調することよりも優れていることが多い。 –

+1

@PeterStreetうん!!そうです...いくつかのツールは、自分たちのようにテイラードレスされていませんが、単一のプロジェクトですべての問題を解決しようとするのではなく、自分のドメインに集中する必要があります:) –

1

あまりにも複雑です。

TryConvertToIConvertableに保存するのに十分です。 ターゲットタイプが適用されない場合は、falseを返すだけです。はい、これはすべてのインスタンスで同じになりますが、ここで間違っていますか?

タプルを返すときに、Try...メソッドのよく知られているパターンを破っていることに注意してください。IMO、これがより身近になります。

public interface IConvertable 
{ 
    bool TryConvertTo<TTarget>(out TTarget entity) 
     where TTarget: Entity, IConvertable 
} 
+0

C#7の名前付きタプル出力でこのコードを準備していますが、これは不器用で酷使された 'out'型よりも使いやすく操作が簡単です。しかし、正しいことを意味するわけではありません:しかし、私はあなたのポイントを得ています - コンストラクタの制限なしでTryConvertToを実行すると潜在的にうまくいくでしょう...ありがとう。 –

+1

@PeterStreetもう1つの選択肢は、['Option '](https://github.com/nlkl/Optional)の値を返すことです - 追加の 'out'パラメータとプリC#7タプルの両方の問題を避けます非記述的なプロパティ名)。 –

+0

質問 - 最終プログラムの実際の変換は、メソッドの構築よりもはるかに進んでいる可能性があるので、他の操作を実行する前に変換不可能な型が入力されていれば「早期に失敗する」ことを望んでいました。これを処理する方法はありますか? –

関連する問題