如何在 abp 样板中将 IApplicationService 调用到 WCF SOAP 服务中?
How to invoke an IApplicationService into a WCF SOAP services in abp Boilerplate?
我使用 abp 样板开发了一个 MVC 应用程序,现在我需要通过 WFC/SOAP.
公开一些服务
想法是创建一个 WFC 服务,注入所需的 IApplicationService
并使用它。
类似于:
// this code does not work
public class MyFirstService : IMyFirstService, ITransientDependency {
private readonly ICourseAppService _courseAppService;
// Injection here does not work!
public MyFirstService(ICourseAppService courseAppService) {
_courseAppService = courseAppService;
}
public CourseDto GetData(int id) {
return _courseAppService.Get(id);
}
}
但是这段代码不起作用。 :-(
我遇到的第一个错误来自 WCF,它说服务没有不带参数的默认构造函数。所以我走错了路
如何将服务注入SOAP服务?
答案对我没有帮助。
WCF 使用反射来创建服务实例,因此如果您的服务没有不带参数的构造函数,wcf 将无法创建服务实例,这就是 wcf 显示错误的原因。
注入框架与wcf集成并不容易
您应该自定义实例提供程序(它提供 wcf 服务实例)。
https://blogs.msdn.microsoft.com/carlosfigueira/2011/05/31/wcf-extensibility-iinstanceprovider/
在您的自定义实例提供程序中,您可以在方法 GetInstance 中提供注入的服务实例。
那么您应该使用服务行为让 wcf 使用您自己的实例提供程序。
例如
public class MyServiceAttribute : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher item in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher item1 in item.Endpoints)
{
item1.DispatchRuntime.InstanceProvider = new MyInstanceProvider(); // apply customized instanceProvider
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
那么你应该自定义一个ServiceHost来应用服务行为。
喜欢
public class MyUnityServiceHost : ServiceHost
{
protected MyUnityServiceHost()
{
}
protected override void OnOpening()
{
base.OnOpening();
if (this.Description.Behaviors.Find<MyServiceAttribute >() == null)
{
this.Description.Behaviors.Add(new MyServiceAttribute ());//add your behavior
}
}
}
最后,您应该自定义 HostFactory 来创建您的自定义服务主机。
https://blogs.msdn.microsoft.com/carlosfigueira/2011/06/13/wcf-extensibility-servicehostfactory/
你可以参考下面类似的讨论。
Injecting data to a WCF service
Abp 使用 Castle Windsor,所以根据 this answer and this article 的建议,我找到了解决方案。
- 导入 nuget 包 Castle.WcfIntegrationFacility 后,我创建了一个新的 WCF 库,并在其中创建了一个
AbbModule
class,我在其中注册了 MyService
(在 pt 中定义) . 3):
[DependsOn(typeof(BookingCoreModule), typeof(BookingApplicationModule))]
public class BookingSoapModule : AbpModule {
public override void Initialize() {
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
IocManager.IocContainer.AddFacility<WcfFacility>().Register(
Component
.For<IMyService>()
.ImplementedBy<MyService>()
.Named("MyService")
);
}
}
- 然后我创建了我的
IMyService
接口(注意它扩展了 ITransientDependency
):
[ServiceContract]
public interface IMyService : ITransientDependency {
[OperationContract]
CourseDto GetCourse(int courseId);
}
- 最后,我使用注入:
构造函数实现了接口
public class MyService : IMySecondService {
private readonly ICourseAppService _courseAppService;
public IAbpSession AbpSession { get; set; }
public ILogger Logger { get; set; }
public MyService(ICourseAppService courseAppService) {
AbpSession = NullAbpSession.Instance;
Logger = NullLogger.Instance;
_courseAppService = courseAppService;
}
public CourseDto GetCourse(int courseId) {
AsyncHelper.RunSync(async () => {
var course = await _courseAppService.Get(courseId);
return course;
});
}
}
我使用 abp 样板开发了一个 MVC 应用程序,现在我需要通过 WFC/SOAP.
公开一些服务想法是创建一个 WFC 服务,注入所需的 IApplicationService
并使用它。
类似于:
// this code does not work
public class MyFirstService : IMyFirstService, ITransientDependency {
private readonly ICourseAppService _courseAppService;
// Injection here does not work!
public MyFirstService(ICourseAppService courseAppService) {
_courseAppService = courseAppService;
}
public CourseDto GetData(int id) {
return _courseAppService.Get(id);
}
}
但是这段代码不起作用。 :-(
我遇到的第一个错误来自 WCF,它说服务没有不带参数的默认构造函数。所以我走错了路
如何将服务注入SOAP服务?
答案
WCF 使用反射来创建服务实例,因此如果您的服务没有不带参数的构造函数,wcf 将无法创建服务实例,这就是 wcf 显示错误的原因。
注入框架与wcf集成并不容易
您应该自定义实例提供程序(它提供 wcf 服务实例)。
https://blogs.msdn.microsoft.com/carlosfigueira/2011/05/31/wcf-extensibility-iinstanceprovider/
在您的自定义实例提供程序中,您可以在方法 GetInstance 中提供注入的服务实例。
那么您应该使用服务行为让 wcf 使用您自己的实例提供程序。
例如
public class MyServiceAttribute : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher item in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher item1 in item.Endpoints)
{
item1.DispatchRuntime.InstanceProvider = new MyInstanceProvider(); // apply customized instanceProvider
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
那么你应该自定义一个ServiceHost来应用服务行为。 喜欢
public class MyUnityServiceHost : ServiceHost
{
protected MyUnityServiceHost()
{
}
protected override void OnOpening()
{
base.OnOpening();
if (this.Description.Behaviors.Find<MyServiceAttribute >() == null)
{
this.Description.Behaviors.Add(new MyServiceAttribute ());//add your behavior
}
}
}
最后,您应该自定义 HostFactory 来创建您的自定义服务主机。 https://blogs.msdn.microsoft.com/carlosfigueira/2011/06/13/wcf-extensibility-servicehostfactory/
你可以参考下面类似的讨论。
Injecting data to a WCF service
Abp 使用 Castle Windsor,所以根据 this answer and this article 的建议,我找到了解决方案。
- 导入 nuget 包 Castle.WcfIntegrationFacility 后,我创建了一个新的 WCF 库,并在其中创建了一个
AbbModule
class,我在其中注册了MyService
(在 pt 中定义) . 3):
[DependsOn(typeof(BookingCoreModule), typeof(BookingApplicationModule))]
public class BookingSoapModule : AbpModule {
public override void Initialize() {
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
IocManager.IocContainer.AddFacility<WcfFacility>().Register(
Component
.For<IMyService>()
.ImplementedBy<MyService>()
.Named("MyService")
);
}
}
- 然后我创建了我的
IMyService
接口(注意它扩展了ITransientDependency
):
[ServiceContract]
public interface IMyService : ITransientDependency {
[OperationContract]
CourseDto GetCourse(int courseId);
}
- 最后,我使用注入: 构造函数实现了接口
public class MyService : IMySecondService {
private readonly ICourseAppService _courseAppService;
public IAbpSession AbpSession { get; set; }
public ILogger Logger { get; set; }
public MyService(ICourseAppService courseAppService) {
AbpSession = NullAbpSession.Instance;
Logger = NullLogger.Instance;
_courseAppService = courseAppService;
}
public CourseDto GetCourse(int courseId) {
AsyncHelper.RunSync(async () => {
var course = await _courseAppService.Get(courseId);
return course;
});
}
}