如何在 Castle Windsor 中配置此 ClientBase class

How to I configure this ClientBase class in Castle Windsor

我在配置 class 在 Castle Windsor 3.3.0.0

中的使用时遇到问题

class是这样的:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class DentalRecordServiceClient : ClientBase<IDentalRecordService>, IDentalRecordService
{
    public DentalRecordServiceClient()
    {
    }

    public DentalRecordServiceClient(string endpointConfigurationName) : base(endpointConfigurationName)
    {
    }

    public DentalRecordServiceClient(string endpointConfigurationName, string remoteAddress) : base(endpointConfigurationName, remoteAddress)
    {
    }

    public DentalRecordServiceClient(string endpointConfigurationName, EndpointAddress remoteAddress) : base(endpointConfigurationName, remoteAddress)
    {
    }

    public DentalRecordServiceClient(Binding binding, EndpointAddress remoteAddress) : base(binding, remoteAddress)
    {
    }

    public int GetNumberOfVisits(string fullname, string city, DateTime dateOfBirth)
    {
        return base.Channel.GetNumberOfVisits(fullname, city, dateOfBirth);
    }
}

我有两个相关接口,如下所示:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[ServiceContractAttribute(ConfigurationName = "IDentalRecordService")]
public interface IDentalRecordService
{
    [OperationContractAttribute(Action = "http://tempuri.org/IDentalRecordService/GetNumberOfVisits", ReplyAction = "http://tempuri.org/IDentalRecordService/GetNumberOfVisitsResponse")]
    int GetNumberOfVisits(string fullname, string city, DateTime dateOfBirth);
}

还有这个:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface IDentalRecordServiceChannel : IDentalRecordService, IClientChannel
{
}

我的温莎城堡配置是这样的:

container.Register(
            Component.For<IDentalRecordService>()
                     .ImplementedBy<DentalRecordServiceClient>());

在我的代码中,我试图通过这一行来解析服务:

var service = container.Resolve<IDentalRecordService>();

但我收到以下错误:

Castle.MicroKernel.ComponentActivator.ComponentActivatorException : ComponentActivator: could not instantiate DentalRecordServiceClient ----> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation. ----> System.InvalidOperationException : Could not find default endpoint element that references contract 'IDentalRecordService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.

我想我意识到我的 Castle Windsor 配置应该指定参数,因此会调用 DentalRecordServiceClient 上的其他构造函数之一,但我不确定我需要如何或需要什么数据来提供它。我完全同意传入虚拟数据,这样 Resolve 行就可以工作了。

有什么帮助吗?提前致谢。

编辑:

好的,我发现我可以使用以下代码直接实例化对象:

var binding = new BasicHttpBinding();
var address = new EndpointAddress("http://myaddress");
var service = new DentalRecordServiceClient(binding, address);

如何通过温莎城堡执行此操作?

TIA

我已经好几年没用 WCF 做过任何事情了,但我认为这与 Windsor 没什么关系。您看到的异常(System.InvalidOperationException)是由客户端的构造函数抛出的,而不是 Windsor。

事实上,如果你要更换你的 var service = container.Resolve<IDentalRecordService>();var service = new DentalRecordServiceClient();结果是一样的。

您需要确保 WCF 配置正确才能正常工作。

至于更新后的答案,您可以使用内联依赖项配置您的服务as explained in the documentation

我发现使用 IOC 设置 WCF 客户端总是有点复杂。在我的例子中,我通常针对创建客户端的工厂方法注册接口。

container.Register(Component.For<IDentalRecordService>().UsingFactoryMethod(c =>
{
    var binding = new BasicHttpBinding();
    var address = new EndpointAddress("http://myaddress");
    var service = new DentalRecordServiceClient(binding, address);
    return service;
}));

也可以将 IDentalRecordService 直接映射到 DentalRecordServiceClient 并使用 Krzysztof Kozmic 指出的内联依赖项,但工厂方法一开始可能更容易理解。 不要犹豫,使用内联依赖项,这也很容易:

container.Register(
    Component.For<BasicHttpBinding>(),
    Component.For<EndpointAddress>().DependsOn(Dependency.OnAppSettingsValue("uri", "endpoint")),
    // you can get the value from anywhere, here it grabs it from the config file
    Component.For<IDentalRecordService>().ImplementedBy<DentalRecordServiceClient>());