19

さまざまなIDbConnectionFactoryインスタンスをFunqに登録してから、サービス内でそれらに直接アクセスするにはどうすればよいでしょうか。名前付きインスタンスはどういうわけかここで機能しますか?

これは、サービス間で異なるデータベースを使用する場合に採用するのに最適なアプローチですか?

ありがとう!

編集:

例 ;)。私はIoCにかなり慣れていないので、ここから離れている可能性がありますが、たとえば、注入したい2つの個別のデータベース接続があるとします。ServiceStackでは、これはGlobal.asaxで行われます。

container.Register<IDbConnectionFactory>(c =>
            new OrmLiteConnectionFactory(@"Connection String 1", SqlServerOrmLiteDialectProvider.Instance));                                             

container.Register<IDbConnectionFactory>(c =>
            new OrmLiteConnectionFactory(@"Connection String 2", SqlServerOrmLiteDialectProvider.Instance));                

これらの両方は、ホンキーなドーリーを注入されているようです。

これらは、次のような方法でサービス側で自動的にアクセスされます。

public IDbConnectionFactory DbFactory { get; set; }

この場合、最初に登録されたものを私に与えているようです。サービス側で特定のものにアクセスするにはどうすればよいですか?うまくいけば、それはそれをもう少し明確にするでしょう。

これがServiceStackの本格的な例です。1つのIDbConnectionFactoryのみを使用する例: Movies Rest

4

5 に答える 5

15

上記の私の質問はまだ有効ですが、とにかく以下があなたを助けるかもしれません。

Funqは自動コンストラクターインジェクション(別名自動配線)をサポートしていないため、Func<T>ラムダ式を作成して手動で行う必要があります。IDbConnectionFactoryコンストラクターの注入は既に手動で行っているため、サービスに注入するものを簡単に選択できます。例:

IDbConnectionFactory yellowDbConFactory =
    new YellowDbConnectionFactory();

IDbConnectionFactory blueDbConFactory =
    new BlueDbConnectionFactory();

IDbConnectionFactory purpleDbConFactory =
    new PurpleDbConnectionFactory();

container.Register<IService1>(c =>
    new Service1Impl(yellowDbConFactory,
        c.Resolve<IDep1>());

container.Register<IService2>(c =>
    new Service2Impl(blueDbConFactory);

container.Register<IService3>(c =>
    new Service3Impl(purpleDbConFactory, 
        c.Resolve<IDep2>());

もちろん、次のような名前付き登録を使用することもできます。

container.Register<IDbConnectionFactory>("yellow",
    new YellowDbConnectionFactory());

container.Register<IDbConnectionFactory>("blue",
    new BlueDbConnectionFactory());

container.Register<IDbConnectionFactory>("purple",
    new PurpleDbConnectionFactory());

container.Register<IService1>(c =>
    new Service1Impl(
        c.Resolve<IDbConnectionFactory>("yellow"),
        c.Resolve<IDep1>());

container.Register<IService2>(c =>
    new Service2Impl(
        c.Resolve<IDbConnectionFactory>("blue"));

container.Register<IService3>(c =>
    new Service3Impl(
        c.Resolve<IDbConnectionFactory>("purple"), 
        c.Resolve<IDep2>());

自動配線のサポートがないため、これらのかなり厄介な登録になり、これはすぐに構成ルートのメンテナンスの悪夢になりますが、それはあなたの質問とは無関係です;-)

通常、登録のあいまいさを防ぐようにしてください。あなたの場合、2つのことを行う(2つのデータベースに接続する)単一のインターフェースがあります。両方のデータベースがまったく同じモデルを共有していない限り、各データベースは独自のインターフェイスに値します(2つの実装が交換可能でない場合、リスコフの置換原則に違反することになります)。

interface IYellowDbConnectionFactory : IDbConnectionFactory
{
}

interface IPurpleDbConnectionFactory : IDbConnectionFactory
{
}

ServiceStackの動作方法により、おそらくそれぞれに実装を実装する必要があります。

class YellowDbConnectionFactory : OrmLiteConnectionFactory,
    IYellowDbConnectionFactory
{
    public YellowDbConnectionFactory(string s) : base(s){}
}

class PurpleDbConnectionFactory : OrmLiteConnectionFactory,
    IPurpleDbConnectionFactory 
{
    public YellowDbConnectionFactory(string s) : base(s){}
}

IDbConnectionFactoryここで、サービスの定義を変更して、 :を使用する代わりに特定のインターフェースを使用する必要があります。

public class MovieService : RestServiceBase<Movie>
{
    private readonly IYellowDbConnectionFactory dbFactory;

    public MovieService(IYellowDbConnectionFactory factory)
    {
        this.dbFactory = factory;
    }
}

このクラスは、プロパティインジェクションの代わりにコンストラクタインジェクションを使用するようになっていることに注意してください。これをプロパティインジェクションで機能させることができますが、通常はコンストラクタインジェクションを使用することをお勧めします。これはそれについてのSOの質問です。

Funqを使用すると、構成は次のようになります。

container.Register<MovieService>(c =>
    new MovieService(
        c.Resolve<IYellowDbConnectionFactory>());

Funqは自動配線をサポートしていないため、これら2つの新しいインターフェイスと2つのクラスに変更してMovieServiceも、あまり効果はありませんでした。あなたはすべてを手動で一緒に配線している人になります。ただし、自動配線をサポートするフレームワークに切り替えると、何を注入するかについての議論がないため、この設計により、コンテナーは問題なく適切な依存関係を注入できます。

于 2012-01-07T00:49:28.570 に答える
11

Funqは自動配線をサポートしていませんが、ServiceStackの実装はサポートしています。ServiceStackの最新バージョンには、Funq.Containerオーバーロードが含まれています。

container.RegisterAutoWired<T>();
container.RegisterAutoWiredAs<T,TAs>();
container.RegisterAs<T,TAs>();

したがって、スティーブンの例では、次のこともできます。

container.RegisterAs<YellowDbConnectionFactory,IYellowDbConnectionFactory>();

そして、それはあなたのために依存関係を自動的に登録します。

于 2012-01-08T13:34:52.057 に答える
3

質問はかなり古いことに気づきましたが、ここで2セントをチップに入れると思いました。ServiceStackからトランザクションDBとロギングDBにアクセスしたかったのですが、これがAppHostBase Configure()メソッドからアクセスすることになった方法です。

            container.Register<IDbConnectionFactory>(
                c => {
                    OrmLiteConnectionFactory dbFactory = new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["MyTransactionalDB"].ConnectionString, MySqlDialect.Provider);
                    dbFactory.ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current);
                    dbFactory.RegisterConnection("LoggingDB", ConfigurationManager.ConnectionStrings["MyLoggingDB"].ConnectionString, MySqlDialect.Provider);

                    return dbFactory;
                });

デフォルトでは、ファクトリから接続を開くときに「MyTransactionalDB」が使用されますが、次の方法でサービスからロギングDBに明示的にアクセスできます。

        using (var db = DbFactory.Open("LoggingDB"))
        {
            db.Save(...);
        }
于 2015-10-25T11:29:40.973 に答える
1

このIoCの代わりにリポジトリパターンを使用してみてください(これは不必要に物事を複雑にするだけです)。上記のコードは機能しないようです。何かが変わったのではないかと疑ってください。IDbConnectionFactoryを登録すると、IDbConnectionプロパティが魔法のように設定される方法についてはまだわかりません。これについての説明が欲しいです。誰かがServiceStackIoCコンテナを使用してこれを機能させる場合は、その方法を確認したいと思います。そして、SSドキュメントを更新することは非常に有益です(私はそれをするのはとてもうれしいです)

于 2013-10-13T19:57:45.267 に答える
1

辞書を使用することもできます

データベースのキー名を使用して列挙型を作成します

public enum Database
    {
        Red,
        Blue
    }

Startup.csで、新しいSqlConnectionを開く関数のディクショナリを作成してから、依存関係ディクショナリをシングルトンとして挿入します。

Dictionary<Database, Func<IDbConnection>> connectionFactory = new()
   {
      { Database.Red, () => new SqlConnection(Configuration.GetConnectionString("RedDatabase")) },
      { Database.Blue, () => new SqlConnection(Configuration.GetConnectionString("BlueDatabase")) }
   };
services.AddSingleton(connectionFactory);

インスタンスを取得した後、次のようにオブジェクトコンストラクターへの依存関係を取得します。

public class ObjectQueries
{
   private readonly IDbConnection _redConnection;
   private readonly IDbConnection _blueConnection;

   public ObjectQueries(Dictionary<Database, Func<IDbConnection>> connectionFactory)
   {
      _redConnection = connectionFactory[Database.Red]();
      _blueConnection = connectionFactory[Database.Blue]();
   }
}

清潔で読みやすいです;)

于 2021-03-04T11:10:22.247 に答える