注入的ISession到自定义valueresolver [英] Inject ISession into custom valueresolver

查看:230
本文介绍了注入的ISession到自定义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< D​​efaultRegistry>();
});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 插件式因此除了你。

我可以在这里想到的一对夫妇的解决方案。 免责声明我没有对它们进行测试。


  1. 将在的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 AutoMapper ValueResolver.

    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 code

    public 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.

    1. 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();
            });
          }
        }
    

    1. Tell AutoMapper you want to use the nested container.

    这篇关于注入的ISession到自定义valueresolver的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆