gpt4 book ai didi

nhibernate - 如何使用 LifestyleScoped 实现 CaSTLe Windsor IScopeAccessor 以提供每个 ViewModel 的 NHibernate session

转载 作者:行者123 更新时间:2023-12-02 03:52:10 25 4
gpt4 key购买 nike

我正在寻找一些帮助来创建 IScopeAccessor 的实现,或者寻找一个新的解决方案,这将使我能够为每个 ViewModel 提供一个 NHibernate session 。

我知道 Windsor 现在支持范围内的生活方式(here)。然而,该示例使用 using block 创建特殊作用域并在 using 中调用 container.resolve。

    _container.Register(Component.For<A>().LifestyleScoped());

using (_container.BeginScope())
{
var a1 = _container.Resolve<A>();
var a2 = _container.Resolve<A>();
Assert.AreSame(a1, a2);
}

我想不出一种方法来完成这项工作,因为我不想传递容器,我希望将范围绑定(bind)到创建的 ViewModel,这将在需要时动态发生。

作为替代方案,我似乎可以创建一个 IScopeAccessor 的实现,根据 Krzysztof Koźmic (here) 的说法,它允许我

"... provide any scope you like. Scope is an abstract term here and it can be anything."

不幸的是,我找不到不特定于基于 Web 的场景的 IScopeAccessor 实现,我正在努力理解我需要做什么才能将“任何东西”变成有效范围。

我找到了一个示例,说明我想使用 Ninject 做什么 (http://www.emidee.net/index.php/2010/08/23/ninject-use-one-database-session-per- View 模型/):

Bind<ISession>().ToMethod(ctx =>
{
var session = ctx.Kernel.Get<....>().BuildSessionFactory().OpenSession();
return session;
})
.InScope(context =>
{
var request = context.Request;

if (typeof(IViewModel).IsAssignableFrom(request.Service))
return request;

while ((request = request.ParentRequest) != null)
if (typeof(IViewModel).IsAssignableFrom(request.Service))
return request;

return new object();
});

在 Ninject 中,InScope 表示只要回调返回的对象保持事件状态,就应该重用绑定(bind)创建的任何实例。本质上,此回调返回根级别 ViewModel(因为 ViewModel 可以嵌套)。

关于如何使用 Windsor 做同样的事情或得到相同的结果有什么想法吗?

最佳答案

问题好像出在创建的地方。如果这完全是关于正在构建的 View 模型的依赖关系,您可以使用 boud 生活方式,如 What's new... 中所述。或者您也可以使用您自己的范围访问器,它对 View 模型很敏感。例如像这样:

public class ViewModelScopeAccessor : IScopeAccessor
{
private IDictionary<Guid, ILifetimeScope> scopes = new Dictionary<Guid, ILifetimeScope>();
private ILifetimeScope defaultScope;

public ViewModelScopeAccessor()
: this(new DefaultLifetimeScope())
{ }

public ViewModelScopeAccessor(ILifetimeScope defaultScope)
{
this.defaultScope = defaultScope;
}

public ILifetimeScope GetScope(CreationContext context)
{
var creator = context.Handler.ComponentModel.Implementation;
var viewModel = creator as IViewModel;
if (viewModel != null)
{
ILifetimeScope scope;
if (!scopes.TryGetValue(viewModel.UID, out scope))
{
scope = new DefaultLifetimeScope();
scopes[viewModel.UID] = scope;
}

return scope;
}
else
{
return defaultScope;
}
}

public void Dispose()
{
foreach (var scope in scopes)
{
scope.Value.Dispose();
}

defaultScope.Dispose();
scopes.Clear();
}
}

对于以下 View 模型界面:

public interface IViewModel
{
string DisplayName { get; }

Guid UID { get; }
}

你当然可以用其他方式比较 View 模型,这只是一个例子。

绑定(bind)的生活方式和范围访问器的缺点是,如果您在 View 模型中使用类型化工厂,它将无法工作以延迟构造对象,因为范围访问器不知道从哪个对象/方法它的工厂方法被调用。但我认为这是一个普遍的 .NET 问题,因为方法实际上永远不知道从哪里调用它。

因此,您可以使用自己的工厂,每个工厂实例只生成一个实例,并使它们也限定在您的 View 模型中。

希望这对您有所帮助。

关于nhibernate - 如何使用 LifestyleScoped 实现 CaSTLe Windsor IScopeAccessor 以提供每个 ViewModel 的 NHibernate session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13976939/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com