【问题标题】:How to invoke an IApplicationService into a WCF SOAP services in abp Boilerplate?如何在 abp Boilerplate 中将 IApplicationService 调用到 WCF SOAP 服务中?
【发布时间】:2023-03-17 20:54:01
【问题描述】:

我使用 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 的回答对我没有帮助。

【问题讨论】:

    标签: wcf soap aspnetboilerplate asp.net-boilerplate


    【解决方案1】:

    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 样板框架时的解决方案,但它让我走上了正确的道路。
    【解决方案2】:

    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;
            });
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-03
      相关资源
      最近更新 更多