6

私のメインのASP.NETMVC複合アプリケーションは、グローバルUnityコンテナーを使用して型を登録します。アプリは、このグローバルコンテナを使用するようにコントローラファクトリを設定します。これをリファクタリングして、ポータブルエリアのそれぞれが独自の子Unityコンテナーを活用し、さまざまなエリアがさまざまな方法でインターフェイスを実装できるようにしたいと思います。エリアごとに異なるControllerFactoryが必要になるようです。以下がすべての工場を設定することを考えると、どうすればそれを達成できますか?

ControllerBuilder.Current
    .SetControllerFactory(/* controller factory with global unity container */);
4

2 に答える 2

11

MasterControllerFactory各領域のすべての実装を含むを使用でき、IControllerFactoryどのファクトリがどの を構築できるかがわかりRequestContextます。これにより、実際には、領域だけでなく、あらゆるバリエーションに対して異なる ControllerFactory を選択できます。仕組みは次のとおりです。

IFilteredControllerFactoryすべてのエリア コントローラ ファクトリの実装は、 の代わりに実装する必要がありIControllerFactoryます。ここにあります:

public interface IFilteredControllerFactory:IControllerFactory
{
    bool CanHandle(RequestContext requestContext);
}  

エリア名に基づいてフィルタリングする実装の例は、次のようになります。

public class Area51ControllerFactory:IFilteredControllerFactory
{
    public bool CanHandle(RequestContext requestContext)
    {
        return requestContext.RouteData.DataTokens["area"].ToString().ToLowerInvariant() == "area51";
    }
    public IController CreateController(RequestContext requestContext, string controllerName)
    {
        // create a controller...
    }

    public void ReleaseController(IController controller)
    {
        // release the controller...
    }

}

MasterControllerFactory次に、次のようなが必要です。

public class MasterControllerFactory : DefaultControllerFactory
{
    private readonly List<IFilteredControllerFactory> _slaveFactories;
    public MasterControllerFactory()
    {
        _slaveFactories = new List<IFilteredControllerFactory>();
    }
    public void RegisterFactory(IFilteredControllerFactory slaveFactory)
    {
        if(slaveFactory!=null && !_slaveFactories.Contains(slaveFactory))
        {
            _slaveFactories.Add(slaveFactory);
        }
    }

    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var factory = _slaveFactories.FirstOrDefault(x => x.CanHandle(requestContext));
        if(factory!=null)
        {
            return factory.CreateController(requestContext, controllerName);
        }
        return base.CreateController(requestContext, controllerName);
    }

    public override void ReleaseController(IController controller)
    {
        bool released = false;
        if (controller is Controller)
        {
            var requestContext = ((Controller) controller).ControllerContext.RequestContext;
            var factory = _slaveFactories.FirstOrDefault(x => x.CanHandle(requestContext));
            if (factory != null)
            {
                factory.ReleaseController(controller);
                released = true;
            }
        }
        if(!released)base.ReleaseController(controller);
    }
}

あなたの Application_Start では、global.asaxまだすべてを設定する必要がありますが、それは簡単です。

var masterControllerFactory = new MasterControllerFactory();
masterControllerFactory.Register(new Area51ControllerFactory());
ControllerBuilder.Current.SetControllerFactory(masterControllerFactory);

明らかに、コーディング スタイルとアプリケーション アーキテクチャで最適に動作するように、さまざまな方法でこれを微調整できます。

于 2011-03-20T06:22:33.847 に答える
-1

エリアごとに異なる工場を持つことはできないと思いますが、単一の工場で、エリアに基づいてコントローラーを別のコンテナーに入れることができます。これをクエリすることで、ファクトリの CreateController メソッドで自分の領域を見つけることができると思いますが、確かではありません

requestContext.RouteData.DataTokens["area"];

whererequestContextはパラメータとして渡されCreateControllerます。

于 2011-03-18T01:54:27.243 に答える