Have a module dependent Injection for State in PRI

2019-09-04 15:42发布

问题:

hi we have a PRISM WPF MVP application, we would like to have a state to share data between the views in the same module. Since PRISM by default doesnt have a state, was wondering if there is any way i could implement this. Presently i have injected a State with Dictionary as back-store, but the problem is its Global i.e available across the modules. i would really like to scope this injection being module specific.

I believe unity allows registering different classes to the same interface based on name, not sure if the only choice i have is to leverage that for my scenario.

Any help would be great! Thanks!

-ioWint

回答1:

I would agree, scoping Unity's type registration with the ModuleName would be a place to start.



回答2:

Inject a local(module level) state object into all the views that want to have share state. If the interface that defines the state object is local to your module then other modules won't be able to reference the state object because they can't reference the interface.

So: If Module A has 3 views that take an object implementing IStatefulContainer (also declared in Module A) and IStatefulContainer is registered with Unity using RegisterInstance rather than just RegisterType you'll have a singleton that is scoped to the module.

My preference would be to have a "State" service that managed state. This could allow you to add more functionality here if you needed it and is a more "Prismy" approach.

EDIT


If you're using this state object across modules then you can do the following:

1)Put the interface in an assembly that will be referenced by any module that wants to use it.

Assembly A

public interface IBlah
{
    string Add(string stateKey, string stateValue);
}





Assembly B (referencing Assembly A)



    public class Module:IModule
    {
    private IUnityContainer _container;

        public Module(IUnityContainer container)
        {
            _container=container;
        }
        public void Initialize()
        {
            IBlah blah1=new BlahContainer();
            IBlah blah2=new BlahContainer();
            _container.RegisterInstance<IBlah>(blah1,"BlahContainer1");
            _container.RegisterInstance<IBlah>(blah2,"BlahContainer2");

        }
    }

Module C(references assembly A)

_container.Resolve<IBlah>("BlahContainer1");
_container.Resolve<IBlah>("BlahContainer2");

Basically, we define the interface in an assembly we're happy to share between modules. Some projects have "Infrastructure" or Common assemblies that contain service interfaces that are used by other modules - this would fit well here.

We then have our module reference the assembly with the contract in it.

At the moment I'm relying on "magic strings" here but there are lots of ways around this.

Hope this is a little more clear.



回答3:

thanks for your updated solution. I was trying to avoid a name based Unity registration, which would force my Presenter in knowing the Modules State registration Key. I was reading stackoverflow posts on Unity and found the discussion over here Is it possible to override parameter values when using Method Injection with Unity? .

After couple of hours of trial and errors, i ended up achieving the desired functionality.

What i have done:

I have a BaseClass for my Modules -> BaseModule:IModule i have a State Property in it which conforms to my IStateService defined in the Infrastructure.Interface. I Instantiate this State property in the BaseModule() constructor. Note: to go with this approach i have to make my Presenter's have a public IStateService State; property..

At the time of registering the Presenter in the module, i am specifying

<UnityContainer>.RegisterType<MyPresenter, new InjectionProperty("State", State).

Am overriding a public property in Presenter which has name "State" with the State instance value defined in the Module. this way i am able to get the Modules State as the State for each of the View's presenter.

Thanks guys for directing me towards a solution.

-ioWint