6

IRepository インターフェイスと、LINQ to SQL DataContext を引数として取る SqlRepository の実装があるとします。同様に、IService インターフェイスと、3 つの IRepository、IRepository、および IRepository を使用するその実装サービスがあるとします。デモコードは次のとおりです。

public interface IRepository<T> { }

public class SqlRepository<T> : IRepository<T>
{
    public SqlRepository(DataContext dc) { ... }
}

public interface IService<T> { }

public class Service<T,T1,T2,T3> : IService<T>
{
    public Service(IRepository<T1> r1, IRepository<T2>, IRepository<T3>) { ... }
}

Service クラスの作成中に、3 つのリポジトリすべてに同じ DataContext を注入する方法はありますか?

4

4 に答える 4

8

あなたがする必要があるのはDatacontext、Unity コンテナーに を登録するときに、構成で次のPerResolveLifetimeManagerいずれかを使用することを確認することだけです。

<type type="<namespace>.DataContext, <assembly>">
    <lifetime type="Microsoft.Practices.Unity.PerResolveLifetimeManager, Microsoft.Practices.Unity" />
</type>

またはコードで:

container.RegisterType<DataContext>(new PerResolveLifetimeManager());

次に、コンテナServiceが必要とする依存関係を解決するたびに、DataContextまったく同じものが提供されます。ただし、解決する次のリクエストでServiceは、新しいDataContext.

于 2011-04-04T16:41:52.420 に答える
3

私はあなたが何をしたいのか知っていると思います。私は同じ船に乗っており、解決策を考え出そうとしています。

My Serviceレイヤーは、今後のリクエストで操作を実行します。実行する内容は、内容によって異なります。それを一連の責任クラスに渡します。呼び出されたサービスメソッドの存続期間内にすべてのクラスに同じコンテキストが渡されるようにしたい

PerResolveLifetimeManagerを指定できます。これまでのところ、それは私のテストケースで機能しているようです:

サービスクラス:

public interface IServiceClass
{
    void DoService();
}

class ServiceClass : IServiceClass
{
    private IHandler Handler { get; set; }

    public ServiceClass(IHandler handler)
    {
        Handler = handler;
    }

    public void DoService()
    {
        Handler.HandleRequest();
    }
}

IHandlerは2つのクラスによって実装され、ChainofResponsibilityパターンを実行します。

    public interface IHandler
{
    void HandleRequest();
}

class Handler : IHandler
{
    private IDataContext DataContext { get; set; }
    public Handler(IDataContext dataContext)
    {
        DataContext = dataContext;
    }

    public void HandleRequest()
    {
        DataContext.Save("From Handler 1");
    }
}

class Handler2 : IHandler
{
    private IDataContext DataContext { get; set; }
    private IHandler NextHandler { get; set; }

    public Handler2(IDataContext dataContext, IHandler handler)
    {
        DataContext = dataContext;
        NextHandler = handler;
    }

    public void HandleRequest()
    {
        if (NextHandler != null)
            NextHandler.HandleRequest();

        DataContext.Save("From Handler 2");
    }
}

ご覧のとおり、両方のハンドラーがIDataContextのインスタンスを受け入れます。これは、両方で同じにしたいと考えています。Handler2は、制御を渡すIHandlerのインスタンスも受け入れます(ここでは両方を示していますが、実際には1つだけが要求を処理します...)

IDataContext。コンストラクターでGuidを初期化し、その操作中に出力して、呼び出されたときに同じインスタンスを使用しているかどうかを確認します。

public interface IDataContext
{
    void Save(string fromHandler);
}

class DataContext : IDataContext
{
    private readonly Guid _guid;

    public DataContext()
    {
        _guid = Guid.NewGuid();
    }

    public void Save(string fromHandler)
    {
        Console.Out.WriteLine("GUI: [{0}] {1}", _guid, fromHandler);
    }
}

最後に、サービスの登録と呼び出し:

    private IUnityContainer container;
    private void InitializeUnity()
    {
        container = new UnityContainer();
        container.RegisterType<IHandler, Handler2>("Handler2",
            new InjectionConstructor(new ResolvedParameter<IDataContext>(), new ResolvedParameter<IHandler>("Handler1")));
        container.RegisterType<IHandler, Handler>("Handler1");
        container.RegisterType<IDataContext, DataContext>(new PerResolveLifetimeManager());
        container.RegisterType<IServiceClass, ServiceClass>("MyClass", new InjectionConstructor(new ResolvedParameter<IHandler>("Handler2")));
    }

    private void CallService()
    {
        var service = container.Resolve<ServiceClass>("MyClass");
        service.DoService();

        // Resolving and calling again to simulate multiple resolves:
        service = container.Resolve<ServiceClass>("MyClass");
        service.DoService();
    }

これは私が得る出力です:

GUI: [f2250055-8a5f-4f80-a1b6-bcc5574138cf] From Handler 1
GUI: [f2250055-8a5f-4f80-a1b6-bcc5574138cf] From Handler 2
GUI: [22a5c0a3-3c5c-4683-807d-bf2b43f3cd0a] From Handler 1
GUI: [22a5c0a3-3c5c-4683-807d-bf2b43f3cd0a] From Handler 2

このテキストの壁があなたの質問に答えてくれることを願っています...申し訳ありませんが、それは私が実装する必要のある解決策を刺激しました...

于 2010-05-29T18:45:10.767 に答える
0

Unity コンテナーに RegisterInstance() メソッドを使用してみましたか? このようなものがうまくいくかもしれません:

public static UnityContainer CreateContainer() { UnityContainer コンテナー = 新しい UnityContainer();

        try
        {
            var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;

            if (section != null)
            {
                section.Containers[0].Configure(container);
            }
        }
        catch (Exception ex)
        {
            TraceLogger.LogMessage("Configurarion Error for Unity Container", ex.Message, TraceEventType.Critical);
            Environment.Exit(1);
        }


        container.RegisterInstance(new DataContext());
        return container;
    }

これで、このコンテナが DataContext を必要とするオブジェクトを構築しようとするたびに、同じインスタンスが渡されます。インスタンスを登録する前に DataContext を構成することもできます。

更新: 1 つのオプション (これが本当に良い方法かどうかはわかりませんが、これでうまくいきました) は、作成するオブジェクトごとに異なるコンテナーを作成することです。何かのようなもの:

UnityContainer container1 = ContainerFactory.CreateContainer();
UnityContainer container2 = ContainerFactory.CreateContainer();
UnityContainer container3 = ContainerFactory.CreateContainer();
MyObject1 object1 = container1.Resolve<MyObject1>();
MyObject2 object2 = container2.Resolve<MyObject2>();
MyObject3 object3 = container3.Resolve<MyObject3>();

またはより要約された方法:

MyObject1 object1 = ContainerFactory.CreateContainer().Resolve<MyObject1>();
MyObject1 object2 = ContainerFactory.CreateContainer().Resolve<MyObject2>();
MyObject1 object3 = ContainerFactory.CreateContainer().Resolve<MyObject3>();

リストを作成したり、ファクトリ パターンを使用したり、方法はたくさんあります。それが役に立てば幸い

于 2009-05-29T16:45:41.950 に答える
0

私があなたの質問を正しく理解していれば (そしてあなたが unity を使用しているのであれば... unity でタグ付けしたのでそうすると思います)、次のようなことができます:

リポジトリの実装では、

[InjectionConstructor]
public SqlRepository(
    [Dependency] DataContext ctx)

ただし、同じ方法でサービス コンストラクターをマークし、コンテナーを使用してサービスとリポジトリを解決する必要があります。DataContext を機能させるには、コンテナー内にある必要もあります。

別のアプローチは、リポジトリで次のようなことを行うことです。

[InjectionMethod]
public void Initialize(
    [Dependency] DataContext ctx

これは、サービス コンストラクターで BuildUp メソッドを使用して Unity を使用する場合に、このメソッドを呼び出すように Unity に指示します...次のようなものです。

unitycontainer.BuildUp<IRepository>(repository);

それはあなたが探しているものではないと思いますが、私が正しい方向に進んでいるかどうか教えてください.

乾杯 / J

于 2009-05-23T15:25:15.923 に答える