Xamarin.forms 用Xamarin形式的Prism重新实例化单例
我如何以Xamarin的形式处理和重新实例化带有Prism/DryIoC的singleton 我正在使用Azure移动应用程序处理离线数据。有时,我需要删除本地sqlite数据库并重新初始化它。不幸的是,MobileServiceClient偶尔会保持db连接打开,并且没有公开的方法来关闭它。建议的解决方案()是处置MobileServiceClient。唯一的问题是,它在DryIoC注册为单身 我不太熟悉DryIoC,也不太熟悉棱柱体和形状。。。但就我个人而言,我看不出有什么办法可以做到这一点 我确实精心策划了一个几乎奏效的计划 在我的ViewModel方法中,当我需要释放数据库时,我触发了一个事件-Xamarin.forms 用Xamarin形式的Prism重新实例化单例,xamarin.forms,prism,dryioc,Xamarin.forms,Prism,Dryioc,我如何以Xamarin的形式处理和重新实例化带有Prism/DryIoC的singleton 我正在使用Azure移动应用程序处理离线数据。有时,我需要删除本地sqlite数据库并重新初始化它。不幸的是,MobileServiceClient偶尔会保持db连接打开,并且没有公开的方法来关闭它。建议的解决方案()是处置MobileServiceClient。唯一的问题是,它在DryIoC注册为单身 我不太熟悉DryIoC,也不太熟悉棱柱体和形状。。。但就我个人而言,我看不出有什么办法可以做到这一点
_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);
}