2

ビジネスロジック層のインターフェイスを使用して公開されるメソッドがあります。それは次のとおりです。

  public interface IMyWorkingClass
  {
       IEnumerable<dynamic> GetSomeList(); 
  }

  public class MyWorkingClass : IMyWorkingClass
  {
      public IEnumerable<dynamic> GetSomeList()
      {  
           dynamic foos = new List<dynamic>();

           dynamic item = new ExpandoObject();

           item.PropOne = (new Foo()).FooPropertyOne;

           item.PropTwo = (new Bar()).BarPropertyOne;

           foos.Add(item);

           return foos;

      }
  }  

  public class Foo
  {
      public int FooId{get;set;}
      public string FooPropertyOne{get;set;}
      public string FooPropertyTwo{get;set;}

  }

  public class Bar 
  {
      public int BarId{get;set;}
      public string BarPropertyOne{get;set;}
      public string BarPropertyTwo{get;set;}

  }

ダイナミック自体については、さまざまな意見や好みがあります。それらは便利だと思います。私の友人の一人は、ダイナミクスは良いと言いましたが、上記での使用方法はそうではありません。提示された議論は、コンパイラが動的オブジェクトで変更されたものをキャッチしないというものでした。ユニットテストでそれらを捕まえることができると思います。だから私は同意しませんでした。あなたの専門家の意見は何ですか?前もって感謝します :)

アップデート

ここにもう少し明確な(うまくいけば)コードがあります:

public interface IMyWorkingClass
{
    IEnumerable<dynamic> GetListOfClassesForStudentDynamicReturn();
    IEnumerable<StudentClassInfo> GetListOfClassesForStudentStaticReturn();

}

public class MyWorkingClass : IMyWorkingClass
{
    public IEnumerable<dynamic> GetListOfClassesForStudentDynamicReturn(Student student)
    {
        dynamic listOfClasses = new List<dynamic>();



         // repository pattern is used in DAL  
        var datafromDB = (StudentCollegeClassRepo.GetQueryable(x=>x.StudentId==student.StudentId)
                          .select(item => new {
                              item.CollegeClassId
                              ,item.CollegeClass.CollegeClassName
                              ,item.IsEnabledForStudent
                          }).ToList();

        foreach (var item in datafromDB)
        {
            dynamic classWithStudent = new ExpandoObject();
            classWithStudent.CollegeClassId = item.CollegeClassId;
            classWithStudent.CollegeClassName = item.CollegeClassName;
            classWithStudent.IsEnabledForStudent = item.IsEnabledForStudent;
            listOfClasses.Add(studentWithClass);
        }


        return listOfClasses;

    }

    public IEnumerable<StudentClassInfo> GetListOfClassesForStudentStaticReturn(Student student)
    {
         // repository pattern is used in DAL  
        var datafromDB = (StudentCollegeClassRepo.GetQueryable(x=>x.StudentId==student.StudentId)
                          .select(item => new StudentClassInfo {
                              CollegeClassId = item.CollegeClassId
                              ,CollegeClassName = item.CollegeClass.CollegeClassName
                              ,IsEnabledForStudent = item.IsEnabledForStudent
                          }).ToList();


        return datafromDB;

    }
}
// this class is like a viewmodel
public class StudentClassInfo
{
    public int CollegeClassId { get; set; }
    public string CollegeClassName { get; set; }
    public bool IsEnabledForStudent { get; set; }
}

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }
}

public class StudentCollegeClass
{
    public int StudentId { get; set; }
    public int CollegeClassId { get; set; }
    public bool IsEnabledForStudent { get; set; }
}

public class CollegeClass
{
    public int CollegeClassId { get; set; }
    public string CollegeClassName { get; set; }


}

うまくいけば、私は物事をもう少し明確にしました。それで、動的リターンを使用するメソッドは問題ありませんか、静的タイプを作成して、代わりにそれを返しますか?私はここで適切に質問する方法も学んでいます..あなたの忍耐と素晴らしい返事に感謝します:)

4

2 に答える 2

6

スキートの言うことにもかかわらず:)ここでいくつかの考えを追加します。

Dynamics を使用する道を歩み始める場合は、考え方を変える必要があります。オブジェクトが何であるかはわかりません。何ができるかだけを気にします。

すぐにインターフェースが必要ないことに気づき、「いったい私は何をしているのだろうか?」と自問します。これは常に尋ねるのに最適な質問です.

そして、コンパイラ チェックの損失をカバーするためにさらにテストを書き始めると、変化が起こります。メソッドをもう少し明確に書き始めるのです。ファクトリやその他のクラスに依存して、これらの不定形の動的グーの小さなビットの上にロジックを課すようになります。

精神的な変化を考えると、信じられないほど解放されます。たとえば、Foo/Bar の上で何かを行う「MyWorkingClass」があります。それが「CheckInvetoryOf(dynamic item)」と呼ばれるいくつかのメソッドを持つ「Warehouse」と呼ばれるフルフィルメント クラスであった場合、物事はもう少し理にかなっています。

現実の世界では、使用できるものの非常に小さなサブセットを公開するインターフェイス (おそらく ITrackable か何か) をここに送信します。それは機能しますが、後でアプローチを変更し、Warehouse にデジタル商品 (ダウンロードなど) を出荷させたい場合はどうすればよいでしょうか?

あなたの Warehouse クラスは、おそらくレンガとモルタルの後に作られ、デジタル ダウンロードの送信に移行しました... ああ、いや!

しかし、ダイナミクスを使えば簡単です。アイテムが IDigitalGood (たとえば) であるかどうかを単純に尋ねて、適切に処理することができます。

だから - あなたが書いたコードは、はい、紛らわしいです。動的言語に時間を費やすと、それほど混乱しないようにするための精神的な変化が得られます。

ああ、あなたがしたことをするための「建築的に間違っている」という点では...誰が知っていますか。紛らわしければ、それは良くありません。それがテストを困難にするなら、それは三重に良くありません。あなたが笑われたら、あなたは正しい軌道に乗っているかもしれません:)

于 2012-11-15T22:45:57.653 に答える
6

では、unknown を返すメソッドを公開するインターフェイスを作成したいと思いますIEnumerableか? IEnumerbleメソッドが返された後にそれらのオブジェクトを使用したい場合にとにかくしなければならないいくつかのキャスト/テスト/オーバーロードを保存する以外に、この場合の汎用バージョンを使用する直接的な利点はありますか?

dynamic場合によっては役立つ可能性があることに異議を唱えるつもりはありません。私の意見では、多くの場合、設計上の欠陥が表示されます。それを使うようになるたびに、私は実際に座って、本当にそれが必要かどうかを考えました. そしてほとんどの場合、いくつかの簡単な変更を加えるだけで、それをなくしてすっきりしたデザインにすることができるという結論に達しました。

この場合、動的なジェネリック型が本当に必要ですか? 私の最初の簡単な推測は、おそらく non-generic を使用できるということですIEnumerable

または、いくつかのキャストを節約したい場合、そこに異なる要素がある場合は、すべての要素に共通の基盤を見つけることができます. 現在、すべてのプロパティが文字列であることがわかりました。または、要素の組み合わせを返したい場合は、いくつかを使用できますTuple<>

本当に多くの異なるオブジェクトの完全な未知の型を返すことになった場合は、 を使用できますがIEnumerable<object>、そのインターフェイス実装の存在理由に疑問を投げかけます。異なる実装間、または単一の実装内でさえ、絶対にあらゆる種類の共通点を持つオブジェクトを返すインターフェイスを作成したことを覚えていません。コントロール、数値、コンポーネント、エンティティなどの可能性がありますが、それらは何かを共有する傾向があります。それがプロパティの場合は、いくつかをパックすることもできますPropertyInfo!

TL:DR; このデザイン パターンが、他の手段では避けられない非常に特殊な目的に役立つという非常に明確なケースを提示できない限り、使用しないことをお勧めします。私IEnumerableの2セント。

于 2012-11-15T22:28:17.510 に答える