注入的ISession到自定义valueresolver [英] Inject ISession into custom valueresolver
问题描述
我试图注入的Isession
的一个实例到自定义的 AutoMapper 的 ValueResolver
。
下面是解析器
公共类ContactTypeResolver
:ValueResolver< Common.Models.ContactType,Models.ContactType>
{
ISession的_session; 公共ContactTypeResolver(ISession的会话)
{
_session =会议;
} 保护覆盖Models.ContactType ResolveCore(Common.Models.ContactType源)
{
返回_session.Load< Models.ContactType>(source.Id);
}
}
我对设立AutoMapper配置文件
this.CreateMap< Models.PhoneNumber,Common.Models.PhoneNumber>()
.ReverseMap()
.ForMember(D => d.Type,O => o.ResolveUsing< ContactTypeResolver>());
我喜欢所以StructureMap登记处登记的解析器
对少于ValueResolver< Common.Models.ContactType,Models.ContactType>>()
。新增< ContactTypeResolver>();
我使用的session-per-请求,我设置会话嵌套容器内部的内 StructureMapDependencyScope.cs
当我加入StructureMap向其中创建了网页API项目。这里的code
公共无效CreateNestedContainer()
{
如果(CurrentNestedContainer!= NULL)
{
返回;
}
CurrentNestedContainer = Container.GetNestedContainer();
CurrentNestedContainer.Configure(C => c.For< ISession的方式>()使用(CTX => ctx.GetInstance< ISessionFactory>()的openSession()));}
这是我的容器是如何设置的。
VAR容器= StructuremapMvc.StructureMapDependencyScope.Container;
GlobalConfiguration.Configuration.DependencyResolver =新StructureMapWebApiDependencyResolver(容器);container.Configure(X =>
{
x.IncludeRegistry< DefaultRegistry>();
});Mapper.Initialize(CFG =>
{
cfg.ConstructServicesUsing(container.GetInstance); 的foreach()(在container.GetAllInstances&LT VAR个人资料;资料&GT)
cfg.AddProfile(配置文件);
});
我甚至尝试使用的服务定位器像这样
this.CreateMap< Models.PhoneNumber,Common.Models.PhoneNumber>()
.ReverseMap()
.ForMember(D => d.Type,O =≠0
.ResolveUsing< ContactTypeResolver>()
.ConstructedBy(StructureMap.ObjectFactory.GetInstance&所述; ContactTypeResolver&GT));
然而,当code运行时我得到一个运行时异常说明
没有默认实例被注册,并且不能用于类型'NHibernate.ISession'自动确定
块引用>我也试过在注入我的容器,也没有工作记录另一种类型。我在想什么?会话实例时获得注入到其他对象。此外,不需要在相同的配置文件的工作依赖注入其他映射就好了。
解决方案我相信@RadimKöhler是正确的。
您父容器(其中AutoMapper类型配置)不具有访问插件类型的嵌套容器中定义。它只是不知道关于
的Isession
的插件式因此除了你。我可以在这里想到的一对夫妇的解决方案。 免责声明我没有对它们进行测试。
- 将在
的ISession的注册
键入你的父容器。您应该能够将其范围的HTTP请求有作为。例如用下面的注册code。我不知道ASP.NET的WebAPI知识,可能有一定的差异,但你明白了吧。
公共类NHibernateRegistry:注册表
{
公共NHibernateRegistry()
{
为<结构方式>()单例()使用(C =方式>新ConfigurationFactory()AssembleConfiguration());
对于< ISessionFactory方式>()辛格尔顿()使用(C => c.GetInstance<结构>()BuildSessionFactory());
对于< ISession的方式>()HybridHttpOrThreadLocalScoped()使用(C =>
{
VAR SessionFactory的= c.GetInstance< ISessionFactory>();
返回sessionFactory.OpenSession();
});
}
}<醇开始=2>
告诉AutoMapper要使用嵌套的容器。 I'm trying to inject an instance of
ISession
into a custom AutoMapperValueResolver
.Here's the resolver
public class ContactTypeResolver : ValueResolver<Common.Models.ContactType, Models.ContactType> { ISession _session; public ContactTypeResolver(ISession session) { _session = session; } protected override Models.ContactType ResolveCore(Common.Models.ContactType source) { return _session.Load<Models.ContactType>(source.Id); } }
I have a profile for setting up AutoMapper
this.CreateMap<Models.PhoneNumber, Common.Models.PhoneNumber>() .ReverseMap() .ForMember(d => d.Type, o => o.ResolveUsing<ContactTypeResolver>());
I register the resolver in a StructureMap registry like so
For<ValueResolver<Common.Models.ContactType, Models.ContactType>>() .Add<ContactTypeResolver>();
I am using session-per-request, and I am set the session inside of a nested container inside of
StructureMapDependencyScope.cs
which was created when I added StructureMap to my Web Api project. Here's the codepublic void CreateNestedContainer() { if (CurrentNestedContainer != null) { return; } CurrentNestedContainer = Container.GetNestedContainer(); CurrentNestedContainer.Configure(c => c.For<ISession>().Use(ctx => ctx.GetInstance<ISessionFactory>().OpenSession())); }
And this is how my container is set
var container = StructuremapMvc.StructureMapDependencyScope.Container; GlobalConfiguration.Configuration.DependencyResolver = new StructureMapWebApiDependencyResolver(container); container.Configure(x => { x.IncludeRegistry<DefaultRegistry>(); }); Mapper.Initialize(cfg => { cfg.ConstructServicesUsing(container.GetInstance); foreach (var profile in container.GetAllInstances<Profile>()) cfg.AddProfile(profile); });
I even tried using the service locator like so
this.CreateMap<Models.PhoneNumber, Common.Models.PhoneNumber>() .ReverseMap() .ForMember(d => d.Type, o => o .ResolveUsing<ContactTypeResolver>() .ConstructedBy(StructureMap.ObjectFactory.GetInstance<ContactTypeResolver>));
However, when the code runs I get a run-time exception stating
No default Instance is registered and cannot be automatically determined for type 'NHibernate.ISession'.
I also tried injecting another type registered in my container, which also did not work. What am I missing? The session instance does get injected into other objects. Also, other mappings that don't require dependency injection in the same profile work just fine.
解决方案I believe @RadimKöhler is right.
Your parent container (where the AutoMapper types are configured) doesn't have access to the plugin types defined in the nested container. It just doesn't know about the
ISession
plugin type hence the exception you get.I can think of a couple solutions here. DISCLAIMER I didn't tested them.
- Move the registration of the
ISession
type to your parent container. You should be able to scope it to HTTP requests there as well.For example with the following registration code. I have no knowledge about ASP.NET WebAPI so there might be some differences but you get the point.
public class NHibernateRegistry : Registry { public NHibernateRegistry() { For<Configuration>().Singleton().Use(c => new ConfigurationFactory().AssembleConfiguration()); For<ISessionFactory>().Singleton().Use(c => c.GetInstance<Configuration>().BuildSessionFactory()); For<ISession>().HybridHttpOrThreadLocalScoped().Use(c => { var sessionFactory = c.GetInstance<ISessionFactory>(); return sessionFactory.OpenSession(); }); } }
这篇关于注入的ISession到自定义valueresolver的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!