C# .NET WCF服务中的Automapper 8.0出现问题
我刚刚将WCF服务项目中的Automapper升级到最新版本8.0.0。通过WCF测试客户端调用服务时,我遇到以下错误: System.InvalidOperationException:'映射程序已初始化。每个应用程序域/进程必须调用Initialize一次。” 使用旧的Automapper版本6.0.2,它可以正常工作,并且不会引发异常。我用一个单独的服务行为类初始化了映射程序 服务类别EdiPartners.cs: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
[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只初始化一次,它将正常工作。否则,您将遇到“映射程序已初始化。您必须为每个应用程序域/进程调用一次初始化”不要忘记提及是谁建议的