如何在Abp Boilerplate中的WCF SOAP服务中调用IApplicationService?

时间:2018-12-31 02:27:30

标签: wcf soap aspnetboilerplate asp.net-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服务?

答案https://stackoverflow.com/a/46048289/752004并没有帮助我。

2 个答案:

答案 0 :(得分:0)

WCF使用Reflection创建服务实例,因此,如果您的服务没有没有参数的构造函数,则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

答案 1 :(得分:0)

Abp使用温莎城堡,因此按照this answerthis article的建议,我找到了解决方案。

  1. 一旦导入了nuget软件包Castle.WcfIntegrationFacility,我创建了一个新的WCF库,并在其中创建了一个AbbModule类,在其中注册了MyService(在第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")
        );
    }
}
  1. 然后我创建了IMyService接口(请注意它扩展了ITransientDependency):
[ServiceContract]
public interface IMyService : ITransientDependency {
    [OperationContract]
    CourseDto GetCourse(int courseId);
}
  1. 最后,我通过使用注入的构造函数实现了该接口:
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;
        });
    }

}