Xamarin.forms 用Xamarin形式的Prism重新实例化单例

Xamarin.forms 用Xamarin形式的Prism重新实例化单例,xamarin.forms,prism,dryioc,Xamarin.forms,Prism,Dryioc,我如何以Xamarin的形式处理和重新实例化带有Prism/DryIoC的singleton 我正在使用Azure移动应用程序处理离线数据。有时,我需要删除本地sqlite数据库并重新初始化它。不幸的是,MobileServiceClient偶尔会保持db连接打开,并且没有公开的方法来关闭它。建议的解决方案()是处置MobileServiceClient。唯一的问题是,它在DryIoC注册为单身 我不太熟悉DryIoC,也不太熟悉棱柱体和形状。。。但就我个人而言,我看不出有什么办法可以做到这一点

我如何以Xamarin的形式处理和重新实例化带有Prism/DryIoC的singleton

我正在使用Azure移动应用程序处理离线数据。有时,我需要删除本地sqlite数据库并重新初始化它。不幸的是,MobileServiceClient偶尔会保持db连接打开,并且没有公开的方法来关闭它。建议的解决方案()是处置MobileServiceClient。唯一的问题是,它在DryIoC注册为单身

我不太熟悉DryIoC,也不太熟悉棱柱体和形状。。。但就我个人而言,我看不出有什么办法可以做到这一点

我确实精心策划了一个几乎奏效的计划

在我的ViewModel方法中,当我需要释放数据库时,我触发了一个事件-

_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(false);
另请注意,根据dadhi,添加了用于快速缓存的规则

稍后当我需要在ViewModel中释放数据库时。。。我通过重置本地db变量并将事件发送到App.xaml.cs来启动

_client = null;
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(true);
\u client=null;
_eventAggregator.GetEvent().Publish(true);
在App.xaml.cs中,我订阅了该事件,并将其绑定到以下方法

private void OnRegisterDatabaseEventPublished()
    {
        RegisterDatabase(Container.GetContainer());

        _eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Publish(register);
    }
private void OnRegisterDatabaseEventPublished()
{
RegisterDatabase(Container.GetContainer());
_eventAggregator.GetEvent().Publish(register);
}
在这里,我只是再次调用RegisterMany,与应用程序启动时的操作完全相同。不需要注销任何东西。通过设置和ifAlreadyRegistered参数(谢谢,dadhi!),DryIoC允许替换对象。然后,我向VM发回一个事件,让它知道数据库已被释放

最后,回到ViewModel,我正在收听已完成的事件。该事件的处理程序会像这样更新对象的本地副本

\u client=((PrismApplication)App.Current.Container.Resolve()

然后我可以根据需要使用新对象。这是关键。没有将上面的_client设置为null并在这里再次解析它,我实际上得到了2个对象副本,并且对方法的调用被击中了2次


希望这能帮助其他人发布他们的Azure移动应用数据库

我不确定XF到底是如何处理这些事情的

但在DryIoc中,为了完全删除或替换服务,需要使用
setup:setup.with(asResolutionCall:true)
注册服务。请阅读此处了解更多详细信息:

更新 这里有两个选项和注意事项适用于纯DryIoc,但可能不适用于XF。但这可能有助于解决问题

    public class Foo
    {
        public IBar Bar { get; private set; }
        public Foo(IBar bar) { Bar = bar; }
    }

    public interface IBar {}
    public class Bar : IBar {}
    public class Bar2 : IBar { }

    [Test]
    public void Replace_singleton_dependency_with_asResolutionCall()
    {
        var c = new Container(rules => rules.WithoutEagerCachingSingletonForFasterAccess());

        c.Register<Foo>();
        //c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
                                            // cause the consumer singleton should be replaced too

        c.Register<IBar, Bar>(Reuse.Singleton,
            setup: Setup.With(asResolutionCall: true));        // required

        var foo = c.Resolve<Foo>();
        Assert.IsInstanceOf<Bar>(foo.Bar);

        c.Register<IBar, Bar2>(Reuse.Singleton,
            setup: Setup.With(asResolutionCall: true),         // required
            ifAlreadyRegistered: IfAlreadyRegistered.Replace); // required

        var foo2 = c.Resolve<Foo>();
        Assert.IsInstanceOf<Bar2>(foo2.Bar);
    }

    [Test]
    public void Replace_singleton_dependency_with_UseInstance()
    {
        var c = new Container();

        c.Register<Foo>();
        //c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
                                            // cause the consumer singleton should be replaced too
        c.UseInstance<IBar>(new Bar());
        var foo = c.Resolve<Foo>();
        Assert.IsInstanceOf<Bar>(foo.Bar);

        c.UseInstance<IBar>(new Bar2());
        var foo2 = c.Resolve<Foo>();
        Assert.IsInstanceOf<Bar2>(foo2.Bar);
    }
公共类Foo
{
公共IBar条{get;private set;}
公共Foo(IBar-bar){bar=bar;}
}
公共接口IBar{}
公共类栏:IBar{}
公共类Bar2:IBar{}
[测试]
public void将_singleton _dependency _替换为_asResolutionCall()
{
var c=new Container(rules=>rules.withoutagercachingsingletonforfasteraccess());
c、 寄存器();
//c、 Register(Reuse.Singleton);/!!!如果被替换依赖项的使用者是Singleton,它将无法工作
//原因消费者单例也应更换
c、 寄存器(重用.Singleton,
setup:setup.With(asResolutionCall:true));//必需
var foo=c.Resolve();
Assert.IsInstanceOf(foo.Bar);
c、 寄存器(重用.Singleton,
setup:setup.With(asResolutionCall:true),//必需
ifAlreadyRegistered:ifAlreadyRegistered.Replace);//必需
var foo2=c.Resolve();
Assert.IsInstanceOf(foo2.Bar);
}
[测试]
public void用_UseInstance()替换_singleton _dependency
{
var c=新容器();
c、 寄存器();
//c、 Register(Reuse.Singleton);/!!!如果被替换依赖项的使用者是Singleton,它将无法工作
//原因消费者单例也应更换
c、 UseInstance(新条());
var foo=c.Resolve();
Assert.IsInstanceOf(foo.Bar);
c、 UseInstance(新的Bar2());
var foo2=c.Resolve();
Assert.IsInstanceOf(foo2.Bar);
}

谢谢,爸爸。我很欣赏你的洞察力!我已经根据你的回答更新了我的问题。对选项进行了一些扩展。
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.GetContainer().Rules.WithoutEagerCachingSingletonForFasterAccess();
...
    RegisterDatabase(containerRegistry.GetContainer());
...
}
_client = null;
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(true);
private void OnRegisterDatabaseEventPublished()
    {
        RegisterDatabase(Container.GetContainer());

        _eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Publish(register);
    }
    public class Foo
    {
        public IBar Bar { get; private set; }
        public Foo(IBar bar) { Bar = bar; }
    }

    public interface IBar {}
    public class Bar : IBar {}
    public class Bar2 : IBar { }

    [Test]
    public void Replace_singleton_dependency_with_asResolutionCall()
    {
        var c = new Container(rules => rules.WithoutEagerCachingSingletonForFasterAccess());

        c.Register<Foo>();
        //c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
                                            // cause the consumer singleton should be replaced too

        c.Register<IBar, Bar>(Reuse.Singleton,
            setup: Setup.With(asResolutionCall: true));        // required

        var foo = c.Resolve<Foo>();
        Assert.IsInstanceOf<Bar>(foo.Bar);

        c.Register<IBar, Bar2>(Reuse.Singleton,
            setup: Setup.With(asResolutionCall: true),         // required
            ifAlreadyRegistered: IfAlreadyRegistered.Replace); // required

        var foo2 = c.Resolve<Foo>();
        Assert.IsInstanceOf<Bar2>(foo2.Bar);
    }

    [Test]
    public void Replace_singleton_dependency_with_UseInstance()
    {
        var c = new Container();

        c.Register<Foo>();
        //c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
                                            // cause the consumer singleton should be replaced too
        c.UseInstance<IBar>(new Bar());
        var foo = c.Resolve<Foo>();
        Assert.IsInstanceOf<Bar>(foo.Bar);

        c.UseInstance<IBar>(new Bar2());
        var foo2 = c.Resolve<Foo>();
        Assert.IsInstanceOf<Bar2>(foo2.Bar);
    }