简体   繁体   中英

How to I configure this ClientBase class in Castle Windsor

I'm having trouble configuring usage of a class in Castle Windsor 3.3.0.0

The class is like this:

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

I have two associated interfaces for it like this:

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

and this:

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

My Castle Windsor configuration is like this:

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

In my code, I'm trying to resolve the service by this line:

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

But I get the following error:

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.

I think I realise that my Castle Windsor config should specify parameters so one of the other constructors on DentalRecordServiceClient is called but I'm not sure how or what data I need to feed it. I'm completely ok for dummy data to be passed in just so the Resolve line works.

Any help? Thanks in advance.

Edit:

Ok, I have found that I can instantiate the object directly using the following code:

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

How can I do this via Castle Windsor?

TIA

It's been years since I've done anything with WCF but I think this has little to do with Windsor. The exception you see (the System.InvalidOperationException ) is thrown by the constructor of your client, not Windsor.

In fact, if you were to replace your var service = container.Resolve<IDentalRecordService>(); with var service = new DentalRecordServiceClient(); the result would be the same.

You need to make sure your WCF configuration is correct for this to work.

As for the updated answer, you can configure your service with inline dependencies as explained in the documentation .

I find WCF clients are always a bit complicated to set up using IOC. In my case I usually register the interface against a factory method that creates the client.

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

It is also possible to map IDentalRecordService directly to DentalRecordServiceClient and to use inline dependencies as pointed out by Krzysztof Kozmic, but factory methods may be easier to understand at first. Don't hesitate to play with inline dependencies, though, it is quite easy too:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM