2011-01-19 11 views
0

私は、データベースへのアクセス(読み書き)のためのリポジトリと呼ばれるクラスを持っています。コンストラクタに基づくメソッドの利用可能性

データベースへのアクセスが必要なプロジェクトは、リポジトリのオブジェクトを作成し、その特定のプロジェクトで動作するリポジトリのコンストラクタパラメータとして接続文字列を渡します。

リポジトリには、特定の接続文字列が渡された場合にのみ使用できるメソッドがいくつかあります。いくつかの異なる接続文字列が渡された場合、それらを使用可能にしたくありません。

私はそれを達成する方法はありますか?

私はメソッドヘッダーテクニックを使ったことがありません。はいの場合、どうすれば使えますか?いいえ、私の目標を達成するための他の方法があれば私に知らせてください。

よろしくお願いいたします。やっての

+0

...おかげですべて一回再び...おそらく – user402186

答えて

0

並べ替え:

if (_connection == "XYZ") 
    throw new InvalidOperationException(); 

が、それはあなたが新しいクラスを作成するために、あなたのアプローチをリファクタリング可能性がある。そして、

public class ConnectionInfo 
{ 
    public string ConnectionString { get; set; } 
    public bool IsLimitedAccess { get; set; } 
} 

のアクセスが制限されている場合、各リポジトリの方法では、許可されていませんnullを返すか、例外などをスローしますか?

+0

代わりに 'IsLimitedAccess'を持つこのの変化は、サポートされているという名前の操作の' 'IListのを持っています。使用可能な操作の集合が接続ごとに異なる場合、特異フラグが十分に柔軟でない可能性がありますか? –

+0

はい、本当、それは... –

1

factory method patternを使用して目標を達成できます。
接続文字列を受け取り、文字列の内容に基づいて別のリポジトリを返すRepositoryFactoryクラスを作成します。

public class RepositoryFactory { 

    public IRepository GetRepository(string connection) 
    { 
     if(SomeTestOnConnect(connection)) 
      return new SimpleRepository(connection); 
     else 
      return new FullRepository(connection); 

    } 
} 

誰かがリポジトリを望むとき、GetRepositoryメソッドを呼び出します。

+0

問題があり、あなたが同じインターフェイスを返すされる深さに行く必要があるかどうかの問題のすべての詳細を知らなく伝えるために、その本当に難しいです。したがって、無効なメソッドはNotImplementedException()をスローする必要がありますか? – NerdFury

+0

True、これはこのメソッドの制限です。呼び出し元は、必要なインスタンスにキャストすることができます。 –

0

追加のメソッドが必要かどうかを事前に知っている場合は、追加のメソッドをサポートしていない基本バージョンとそうでない派生型を持つことができます。必要な情報が提供されない場合、派生型のコンストラクタは例外をスローする可能性があります。

コンストラクタの代わりにファクトリメソッドを使用すると、渡された接続文字列に基づいてベースまたはファンシーオブジェクトを構築できます。ただ1つのファクトリメソッドがあれば、余分なメソッドを使いたい場合は、結果を型キャストする必要があります。

少なくとも、要求された型と同程度のオブジェクトを返すか、そうでない場合は例外をスローすることが保証されている、それぞれの定義された型のファクトリメソッドを持つのが最適な方法です。このアプローチは、さらに派生した型が利用可能になった場合の将来の拡張を可能にする。

0

利用可能なメソッドを制限したい場合は、このようなパターンを使用できます。

このようなインスタンスを取得するために工場を使用します。

var repo = RepositoryFactory.Resovle<IFullRepository>("connection string"); 

そして、この仕事をするコードはここにある

欠点がある
public class RepositoryFactory 
{ 
    public static T Resovle<T>(string connection) where T: IRepository 
    { 
     IRepository instance = new Repository(connection); 
     return (T)instance; 
    } 

    private class Repository : IFullRepository 
    { 
     private string _connection; 

     public Repository(string connection) 
     { 
      _connection = connection; 
     } 

     public object Get(int id) 
     { 
      // select 
     } 

     public void Save(object o) 
     { 
      // upate 
     } 

     public void Create(object o) 
     { 
      // create 
     } 

     public void CustomMethodOne() 
     { 
      // do something specialized 
     } 

     public void CustomMethodTwo() 
     { 
      // do something specialized 
     } 
    } 
} 

public interface IRepository 
{ 
    object Get(int id); 
    void Save(object o); 
    void Create(object o); 
} 

public interface IRepositoryProjectOne: IRepository 
{ 
    void CustomMethodOne(); 
} 

public interface IRepositoryProjectTwo: IRepository 
{ 
    void CustomMethodTwo(); 
} 

public interface IFullRepository: IRepositoryProjectOne, IRepositoryProjectTwo 
{ 

} 

、あなたは何を制御するためのインタフェースの爆発を取得しますメソッドが公開されます。ただし、さまざまなインターフェイス間でキャストすることは可能ですが、メソッドが実装されていないときに例外をスローする必要はありません。

0

しかし、私はあなたの呼び出し元のメソッドは、別のポスターは、メソッドの利用可能性を述べているように、リポジトリへの書き込みを許可するかどうかを知るために必要だと思いますが必要なものである、これを行うのに最適な方法はないようです実行時ではなくコンパイル時に知られるようにする。

の解決策は、2つのインタフェース、完全な機能と制限された機能を提供しています1を提供しています1を作成することです。

public interface IRepository : IRead 
    { 
     void Write(object o); 
    } 

    public interface IRead 
    { 
     object Read(); 
    } 

リポジトリオブジェクトがトップインターフェイスを実装しています。

public class Repository : IRepository 
    { 
     private readonly string _connectionString; 
     public Repository(string connectionString) 
     { 
      _connectionString = connectionString; 
     } 
     public object Read() 
     { 
      // Do stuff 
     } 

     public void Write(object o) 
     { 
      // Do stuff 
     } 
    } 

あなたは、接続文字列は、読み取り専用のリポジトリを要求したりせず、インタフェースの指定された型を返すために、2種類の方法を公開するかどうかを判断するクラスを持つことができます(コンパイル時にタイプを知っておく必要があるという意味) 。

public static class RepositoryFactory 
    { 
     public static bool ConnectionStringIsReadOnly(string connectionString) 
     { 
      return connectionString.Contains("user=hacker"); 
     } 

     public static IRead GetReadOnlyRepository(string connectionString) 
     { 
      return new Repository(connectionString); 
     } 

     public static IRepository GetRepository(string connectionString) 
     { 
      if (ConnectionStringIsReadOnly(connectionString)) throw new ArgumentException(@"Given connectionString is not allowed full repository access", "connectionString"); 
      return new Repository(connectionString); 
     } 
    } 

次のようにあなたは、あなたはあなたがIRepositoryのかだけIREADのバージョンを持っていることを確認することでフルアクセスを必要とするアクションを実行しようポイントをseperating、これを消費することができます。すべてのご提案をお寄せいただきありがとうございますが、私は「ONE」はこれに答えていない... tiは、私はそれに行くだろうと思い、FactoryRepository /インタフェースの提案がより採用可能見つけBUがあると思い

public class Program 
    { 
     public void ConsumeRepository(string connectionString) 
     { 
      IRead reader = null; 
      IRepository repository = null; 
      if (RepositoryFactory.ConnectionStringIsReadOnly(connectionString)) 
       reader = RepositoryFactory.GetReadOnlyRepository(connectionString); 
      else 
      { 
       repository = RepositoryFactory.GetRepository(connectionString); 
       reader = repository; 
      } 

      object o = reader.Read(); 

      // do something with o 

      // if allowed then write o to repository 
      if (repository != null) 
      { 
       repository.Write(o); 
      } 
     } 
    } 
関連する問題