C# .NET WCF服务中的Automapper 8.0出现问题

C# .NET WCF服务中的Automapper 8.0出现问题,c#,.net,wcf,automapper,C#,.net,Wcf,Automapper,我刚刚将WCF服务项目中的Automapper升级到最新版本8.0.0。通过WCF测试客户端调用服务时,我遇到以下错误: System.InvalidOperationException:'映射程序已初始化。每个应用程序域/进程必须调用Initialize一次。” 使用旧的Automapper版本6.0.2,它可以正常工作,并且不会引发异常。我用一个单独的服务行为类初始化了映射程序 服务类别EdiPartners.cs: [AutomapServiceBehavior] [ServiceBeha

我刚刚将WCF服务项目中的Automapper升级到最新版本8.0.0。通过WCF测试客户端调用服务时,我遇到以下错误:

System.InvalidOperationException:'映射程序已初始化。每个应用程序域/进程必须调用Initialize一次。”

使用旧的Automapper版本6.0.2,它可以正常工作,并且不会引发异常。我用一个单独的服务行为类初始化了映射程序

服务类别EdiPartners.cs

[AutomapServiceBehavior]
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = 
InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class EdiPartners : IPartners
{
    [FaultContract(typeof(ExceptionObject))]
    public Supplier GetPartnerData(string SupplierNumber)
    {
       // Code
    }
}
    public sealed class AutomapServiceBehavior : Attribute, IServiceBehavior
    {
    #region IServiceBehavior Members

    public void AddBindingParameters(ServiceDescription serviceDescription, 
    ServiceHostBase serviceHostBase,
    Collection<ServiceEndpoint> endpoints, BindingParameterCollection 
    bindingParameters)
    {
        AutomapBootstrap.InitializeMap();
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    #endregion
}
   public class AutomapBootstrap
{
    public static void InitializeMap()
    {
        Mapper.Initialize(config =>
        {
            config.CreateMap<Supplier, IEdiPartnerData>();
            config.CreateMap<IEdiPartnerData, Supplier>();
            config.CreateMap<IEdiPartner, EdiPartner>();

        });
    }
}
服务行为类别汽车服务行为

[AutomapServiceBehavior]
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = 
InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class EdiPartners : IPartners
{
    [FaultContract(typeof(ExceptionObject))]
    public Supplier GetPartnerData(string SupplierNumber)
    {
       // Code
    }
}
    public sealed class AutomapServiceBehavior : Attribute, IServiceBehavior
    {
    #region IServiceBehavior Members

    public void AddBindingParameters(ServiceDescription serviceDescription, 
    ServiceHostBase serviceHostBase,
    Collection<ServiceEndpoint> endpoints, BindingParameterCollection 
    bindingParameters)
    {
        AutomapBootstrap.InitializeMap();
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    #endregion
}
   public class AutomapBootstrap
{
    public static void InitializeMap()
    {
        Mapper.Initialize(config =>
        {
            config.CreateMap<Supplier, IEdiPartnerData>();
            config.CreateMap<IEdiPartnerData, Supplier>();
            config.CreateMap<IEdiPartner, EdiPartner>();

        });
    }
}
公共密封类AutompServiceBehavior:属性,IServiceBehavior
{
#区域代理行为成员
public void AddBindingParameters(ServiceDescription ServiceDescription,
ServiceHostBase ServiceHostBase,
集合终结点,BindingParameterCollection
绑定参数)
{
AutomapBootstrap.InitializeMap();
}
公共无效ApplyDispatchBehavior(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
公共无效验证(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
#端区
}
静态自动映射初始化类自动映射

[AutomapServiceBehavior]
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = 
InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class EdiPartners : IPartners
{
    [FaultContract(typeof(ExceptionObject))]
    public Supplier GetPartnerData(string SupplierNumber)
    {
       // Code
    }
}
    public sealed class AutomapServiceBehavior : Attribute, IServiceBehavior
    {
    #region IServiceBehavior Members

    public void AddBindingParameters(ServiceDescription serviceDescription, 
    ServiceHostBase serviceHostBase,
    Collection<ServiceEndpoint> endpoints, BindingParameterCollection 
    bindingParameters)
    {
        AutomapBootstrap.InitializeMap();
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    #endregion
}
   public class AutomapBootstrap
{
    public static void InitializeMap()
    {
        Mapper.Initialize(config =>
        {
            config.CreateMap<Supplier, IEdiPartnerData>();
            config.CreateMap<IEdiPartnerData, Supplier>();
            config.CreateMap<IEdiPartner, EdiPartner>();

        });
    }
}
公共类自动标签
{
公共静态无效初始值映射()
{
初始化(配置=>
{
config.CreateMap();
config.CreateMap();
config.CreateMap();
});
}
}
也许你们能帮我。我不明白为什么它是与旧的工作,而不是与新版本。在WCF服务中初始化Automapper有更好的方法吗

Thx提前,
Sandro

因为您的服务是InstanceContextMode。PerCall每次调用都将创建一个新实例。此外,由于您已使用
[AutomapServiceBehavior]
装饰了您的服务,因此它将不是针对每个AppDomain(如错误所述)而是针对每个实例初始化一次

因此,请将代码更改为:

public sealed class AutomapServiceBehavior : Attribute, IServiceBehavior
{
    static bool _initialised;

#region IServiceBehavior Members
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
        if (_initialised)  // already init'd per this AppDomain
            return;

        AutomapBootstrap.InitializeMap();
        _initialised = true;
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
#endregion
}
公共密封类AutompServiceBehavior:属性,IServiceBehavior
{
静态布尔值初始化;
#区域代理行为成员
public void AddBindingParameters(ServiceDescription ServiceDescription、ServiceHostBase ServiceHostBase、集合终结点、BindingParameterCollection bindingParameters)
{
if(_initialized)//已为此AppDomain初始化
返回;
AutomapBootstrap.InitializeMap();
_初始化=真;
}
公共无效ApplyDispatchBehavior(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
公共无效验证(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
#端区
}
有用的服务行为还是自定义服务主机?
顺便说一句,
AutomapServiceBehavior
可能不是编写服务行为的好例子,因为如果您打算在同一个程序集中使用它(可能使用不同的映射)装饰多个服务,它将不起作用。AutoMapper喜欢在应用程序启动时初始化一次,因此如果要在任何地方初始化,我会将其放入自定义
ServiceHost
中,并消除该行为。

解决方案是实现自定义服务主机工厂类:

public class EdiPartnersFactory : ServiceHostFactory
{
   protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
   {
    // Initialize Automapper
    AutomapBootstrap.InitializeMap();

    var host = new ServiceHost(serviceType, baseAddresses);

    return host;
    }
}
我更改了服务合同和绑定的web.config:

    <system.serviceModel>
  <services>
    <service name="Company.Sap.EdiPartners"
             behaviorConfiguration="MEXServiceTypeBehavior">
      <endpoint address=""
                binding="basicHttpBinding"
                contract="Company.Sap.IPartners" />
      <endpoint address="mex"
                binding="mexHttpBinding"
                contract="IMetadataExchange" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="MEXServiceTypeBehavior">
        <serviceMetadata httpGetEnabled="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

顺便说一句,当
InstanceContextMode=InstanceContextMode.PerCall
时,
ConcurrencyMode.Multiple
没有意义。无法共享服务器不确定它是否与您的问题相关,但您可以更改冗余供应商IEdiPartnerData映射(来回),而使用
config.CreateMap().ReverseMap()
@MickyD see@Edword thx,因为旧版本没有抛出此方法。但是你的密码被破解了。谢谢你救了我一天。我已通过服务主机工厂实施了您的建议。我会分开发的。我真的很困惑。如果我们按照您的建议检查_initialized,那么每个应用程序域只会发生一次初始化,因为static _initialized是一个应用程序状态变量。那么为什么汽车制造商不能正常工作呢?另外,如果我想按照您的建议使用定制服务主机,就像Sandro发布的答案一样,我是否需要为每个服务类创建一个单独的工厂?@Karamafrooz AutoMapper如果每个AppDomain只初始化一次,它将正常工作。否则,您将遇到“映射程序已初始化。您必须为每个应用程序域/进程调用一次初始化”不要忘记提及是谁建议的