2

仕事に関しては、特定の種類のレコードが入ってきますが、各プロジェクトには独自の実装があります。列などは異なりますが、一般的なプロセスは同じです (レコードがバッチに分割される、バッチが割り当てられる、バッチが完了する、バッチが返される、バッチが送信されるなど)。列の多くも共通ですが、名前が変更されることがあります (ある BatchId と別の Id。[Column("name")] がこの問題を処理します)。

現在、これは、インターフェイスで指定された共通コンポーネントを使用したバッチ割り当て機能の実装のために私が持っているものです:

public interface IAssignment
{
   // properties
   ...
   // methods
   T GetAssignmentRecord<T>(int UserId, int BatchId) where T : IAssignment;
   List<T> GetAssignmentRecords<T>(int UserId) where T : IAssignment;
}

現在、バッチ割り当てを持つ 2 つのプロジェクトがあります。これらは EntityFramework で行われるため、名前空間 1 の割り当てと名前空間 2 の割り当てはまったく異なるものですが、それらを返すためのすべてのメソッドを駆動する特定の共通コンポーネント (ID、割り当てられたユーザー、チェックインなど) によってバインドされます。

私の主な質問は、これを間違って行っているかどうか、およびこれを達成するためのより良い方法があるかどうかであり、データをコントローラーにパイプして、コントローラーをプロジェクトごとに似たように見せながら、メソッドの多くを機能させることができるかどうかです。自動的に処理されます(主に、更新を行う必要があるときに「1つを修正してすべてを修正する」シナリオが発生するようにするため)。

以下は、namespace1 の実装方法の例です。

public class Assignment
{
    ...
    public T GetAssignmentRecord<T>(int UserId, int BatchId) where T : IAssignment
    {
        var db = new Database1Context();
        return (T) Convert.ChangeType(db.Assignment.Where(c => c.UserId == UserId && c.BatchId == BatchId && c.Assigned).First(), typeof(T));
    }
}

コントローラーで:

Assignment assignment = new Assignment();
var record = assignment.GetAssignmentRecord<Assignment>(userid, batchid);
// do stuff

コントローラーのコードは、実際に私が想定している方法です。割り当てクラスを完了しましたが、適切な方法で行っているかどうか当惑しています。これが間違っているかもしれないと私が感じる理由は、基本的に「インターフェイスがジェネリックを探している、エンティティ フレームワークを使用してデータベースから強力な型指定されたオブジェクトを取得している、それをジェネリックにキャストしている、と言っているからです。 「リクエストを作成しています。最初にジェネリックに変換したのと同じ厳密に型指定されたオブジェクトを求めています。」

これを行うより良い方法はありますか?それとも、私が行くべきまったく別の方向ですか?

4

3 に答える 3

3

あなたの目標が何であるかを正しく理解していれば、たとえばこのようにします...

interface IAssignment
{
}

interface IRepo<out T> where T : IAssignment
{
    T GetAssignmentRecord(int UserId, int BatchId);
    IEnumerable<T> GetAssignmentRecords(int UserId);
}

class AssignmentRecord : IAssignment
{
}
class AssignmentWeb : IAssignment
{
}

class RepoDb : IRepo<AssignmentRecord>
{
    public AssignmentRecord GetAssignmentRecord(int UserId, int BatchId)
    {
        //using(var db = new MyDbContext())
        //{
        //    return db.Assignment.Where(c => c.UserId == UserId && c.BatchId == BatchId && c.Assigned).First();
        //}
        return new AssignmentRecord();
    }

    public IEnumerable<AssignmentRecord> GetAssignmentRecords(int UserId)
    {
        //using(var db = new MyDbContext())
        //{
        //    return db.Assignment.Where(c => c.UserId == UserId && c.BatchId == BatchId && c.Assigned);
        //}
        return new List<AssignmentRecord> 
            {
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
            };
    }
}

class RepoWeb : IRepo<AssignmentWeb>
{
    public AssignmentWeb GetAssignmentRecord(int UserId, int BatchId)
    {
        // fetch it from some web service...
        return new AssignmentWeb();
    }

    public IEnumerable<AssignmentWeb> GetAssignmentRecords(int UserId)
    {
        //using(var db = new MyDbContext())
        //{
        //    return db.Assignment.Where(c => c.UserId == UserId && c.BatchId == BatchId && c.Assigned);
        //}
        return new List<AssignmentWeb> 
            {
                new AssignmentWeb(),
                new AssignmentWeb(),
                new AssignmentWeb(),
            };
    }
}

class MYController
{
    public IRepo<IAssignment> Repository { get; set; } // you can inject this e.g. DI

    public IAssignment GetAssignment(int userid, int batchid)
    {
        return Repository.GetAssignmentRecord(userid, batchid);
    }

    public IEnumerable<IAssignment> GetAllAssignments(int userid)
    {
        return Repository.GetAssignmentRecords(userid);
    }
}

class ProgramAssignment
{
    static void Main(string[] args)
    {
        try
        {
            var controller = new MYController();
            controller.Repository = new RepoDb();

            IAssignment assignment = controller.GetAssignment(0, 0);
            IEnumerable<IAssignment> all = controller.GetAllAssignments(0);

            controller.Repository = new RepoWeb();

            assignment = controller.GetAssignment(0, 0);
            all = controller.GetAllAssignments(0);
        }
        catch
        {
            Console.WriteLine("");
        }
    }
}

理由についてはout、私の他の投稿で詳しく説明しています...

独自のタイプまたはサブタイプのみのセットを子として含むジェネリック クラスを作成する方法は?

于 2013-03-28T17:49:04.907 に答える
1

2 つの割り当てに異なるプロパティ (おそらくいくつかの追加) があるが、一部のプロパティは同じであり、それらが異なるデータベースからのものであると仮定すると、それを行うには多くの方法があります。しかし、(私にとって)「最善」は、依存性注入を行うことです。

Assignment クラスのアクティビティ (メソッド) は、別の「サービス」クラスに移動する必要があります。これにより、Assignment は POCO になっただけなので、モジュール性が向上します。

データ アクセスの場合は、データを取得/挿入/更新/削除するための別のクラス (リポジトリ) を作成します。例は次のようになります。

public AssignmentRepository: IAssignmentRepository{
  public Assignment GetAssignmentRecord(int userId, int batchId){

  }
}

public BatchAssignmentRepository: IAssignmentRepository{
  public Assignment GetAssignmentRecord(int userId, int batchId){

  }
}

リポジトリが 1 つではなく 2 つある理由を尋ねると、コードが冗長になりますか? はい、そうですが、モジュール性が高まることも考慮する必要があります。BatchAssignment で何かを変更した場合 (おそらく、列名を変更したり、列を追加したりするなど)、Assignment で同じことを適用する必要はなく、内部の "if batchAssignment else" ロジックを回避します。

呼び出し元からの使用は次のようになります。

IAssignmentService service = new AssignmentService();
IAssignmentRepository repository = new AssignmentRepository();
Assignment a = repository.GetAssignmentRecord(userId, batchId);
service.DoSomething(a);
于 2013-03-28T17:50:55.523 に答える
1

アダプター層について考えてみてください。そのレイヤーは、着信データを共通の構造/クラスに変換する必要があり、ジェネリックに関係なく、一貫して処理できます。もちろん、「アウトバウンド」側でも、特定のデータベースが期待するものに再変換します。これは、他のデータソースで定義されていないデータがデータソースにないこと、または欠落しているデータに対して有効なデフォルト値を定義できることを前提としています。

プロジェクトごとに異なるアダプターが必要だと思います。おそらく、これは依存性注入の仕事です。基本的に、実行時に必要な特定のコード (アダプター クラス) をフェッチします。

ユニティの紹介。

于 2013-03-28T17:52:48.587 に答える