3

この問題を抱えている人を他に見つけていないので、これが起こっているのは私自身のせいだと思います. WCF とキャッスル ウィンザー IoC コンテナーに関しては、私は非常に緑色なので、これがおそらくこれが起こっている最初の理由でしょう。とにかく、私はこれに数日間苦労してきましたが、まだその理由を見つけていません。

まず、Castle Windsor を使用してサービスを登録しました。

var baseUri = new Uri("http://localhost:49246");

_container = new WindsorContainer();

var returnFaults = new ServiceDebugBehavior
{
    IncludeExceptionDetailInFaults = true,
    HttpHelpPageEnabled = true
};
var metadata = new ServiceMetadataBehavior { HttpGetEnabled = true };

_container.Register(
    Component.For<IServiceBehavior>().Instance(returnFaults),
    Component.For<IServiceBehavior>().Instance(metadata));

var baseUri = new Uri("http://localhost:49246");

_container = new WindsorContainer();

var returnFaults = new ServiceDebugBehavior
{
    IncludeExceptionDetailInFaults = true,
    HttpHelpPageEnabled = true
};
var metadata = new ServiceMetadataBehavior { HttpGetEnabled = true };

_container.Register(
    Component.For<IServiceBehavior>().Instance(returnFaults),
    Component.For<IServiceBehavior>().Instance(metadata));

_container
    .Register(
        Component
            .For<IAccountDataAccessor>()
                .ImplementedBy<AccountDataAccessor>(),
        Component
            .For<IInstitutionDataAccessor>()
                .ImplementedBy<InstitutionDataAccessor>(),
        Component
            .For<IRelationshipDataAccessor>()
                .ImplementedBy<RelationshipDataAccessor>(),
        Component
            .For<ITransactionDataAccessor>()
                .ImplementedBy<TransactionDataAccessor>()

    );

_container.AddFacility<WcfFacility>(f => { f.CloseTimeout = TimeSpan.Zero; });
_container.Register(
    Component
        .For<IAccountDataService>()
        .ImplementedBy<AccountDataService>()
        .Named("AccountDataService")
        .LifeStyle.Is(Castle.Core.LifestyleType.Singleton)
        .AsWcfService(new DefaultServiceModel()
            .AddBaseAddresses(baseUri)
            .AddEndpoints(WcfEndpoint
                .ForContract(typeof(IAccountDataService))
                .BoundTo(new WSHttpBinding()))),
    Component
        .For<IInstitutionDataService>()
        .ImplementedBy<InstitutionDataService>()
        .Named("InstitutionDataService")
        .LifeStyle.Is(Castle.Core.LifestyleType.Singleton)
        .AsWcfService(new DefaultServiceModel()
            .AddBaseAddresses(baseUri)    
            .AddEndpoints(WcfEndpoint
                .ForContract(typeof(IInstitutionDataService))
                .BoundTo(new WSHttpBinding()))),
    Component
        .For<IRelationshipDataService>()
        .ImplementedBy<RelationshipDataService>()
        .Named("RelationshipDataService")
        .LifeStyle.Is(Castle.Core.LifestyleType.Singleton)
        .AsWcfService(new DefaultServiceModel()
            .AddBaseAddresses(baseUri)
            .AddEndpoints(WcfEndpoint
                .ForContract(typeof(IRelationshipDataService))
                .BoundTo(new WSHttpBinding()))),
    Component
        .For<ITransactionDataService>()
        .ImplementedBy<TransactionDataService>()
        .Named("TransactionDataService")
        .LifeStyle.Is(Castle.Core.LifestyleType.Singleton)
        .AsWcfService(new DefaultServiceModel()
            .AddBaseAddresses(baseUri)    
            .AddEndpoints(WcfEndpoint
                .ForContract(typeof(ITransactionDataService))
                .BoundTo(new WSHttpBinding()))));

AccountDataService のサービス参照を取得しようとすると、問題なく動作し、エラーは発生しません。しかし、InstitutionDataService へのサービス参照を追加しようとすると、次のような例外がスローされます。

    Could not find a component with name InstitutionDataService, did you forget to register it?

これは非常に苛立たしいものであり、Castle Windsor のドキュメント (またはドキュメントの欠如) で明確な答えを見つけることができないようです。そして、このSOの質問で提案されているソリューションを実装しようとしました:

そう質問

しかし、これもうまくいきませんでした。どのコンポーネントも登録されていないようです。また、役立つ場合は、これが私の svc マークアップです。

    <%@ ServiceHost Language="C#" Debug="true" Service="AccountDataService"
Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" %>

そしてそれはどのサービスも同じです。

私の質問は、私のコンポーネントが AccountDataService と共に登録されないのはなぜですか?

4

2 に答える 2

3

app.config ファイルを使用せずにコードを使用して構成する方法を次に示します。

1 つの違いは、IServiceBehavior に登録する代わりに、DefaultServiceModel で PublishMetadata メソッドを使用していることです。正直に言うと、同じインターフェースが 2 回登録されていて、それがデコレーター パターンでない場合、Windsor がどのように動作するかはわかりません ( Windsor とデコレーターに関するこの記事を参照してください)。

もう 1 つの違いは、AddBaseAddress メソッドでサービスごとに一意のアドレスを指定していることです。各サービスには一意のアドレスが必要ですが、WcfEndpoint の At() メソッドを使用して、サービスごとにそのベース アドレスに関連する複数の一意のエンドポイントを公開できます。(つまり、同じサービスの BasicHttpEndpoint と WSHttpEndpoint を公開する場合)

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Castle.Facilities.WcfIntegration;
using Castle.MicroKernel.Registration;
using Castle.Windsor;

namespace DISandbox
{
    public class Program
    {
        private static WindsorContainer _container;

        public static void Main(string[] args)
        {
            _container = new WindsorContainer();
            _container.AddFacility<WcfFacility>();

            ServiceDebugBehavior returnFaults = new ServiceDebugBehavior
            {
                IncludeExceptionDetailInFaults = true,
                HttpHelpPageEnabled = true,
            };

            _container.Register(
                Component.For<IServiceBehavior>().Instance(returnFaults));

            string baseAddress = "http://localhost:49246/";

            _container.Register(
                Component
                    .For<IAccountDataService>()
                    .ImplementedBy<AccountDataService>()
                    .AsWcfService(new DefaultServiceModel()
                        .PublishMetadata(mex => mex.EnableHttpGet())
                        .AddBaseAddresses(baseAddress + "AccountDataService")
                        .AddEndpoints(WcfEndpoint
                            .ForContract<IAccountDataService>()
                            .BoundTo(new WSHttpBinding()))),
                Component
                    .For<IInstitutionDataService>()
                    .ImplementedBy<InstitutionDataService>()
                    .AsWcfService(new DefaultServiceModel()
                        .PublishMetadata(mex => mex.EnableHttpGet())
                        .AddBaseAddresses(baseAddress + "InstitutionDataService")
                        .AddEndpoints(WcfEndpoint
                            .ForContract<IInstitutionDataService>()
                            .BoundTo(new WSHttpBinding()))));

            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }
    }

    [ServiceContract]
    public interface IAccountDataService
    {
        [OperationContract]
        void DoStuff();
    }

    public class AccountDataService : IAccountDataService
    {
        public void DoStuff() { }
    }

    [ServiceContract]
    public interface IInstitutionDataService
    {
        [OperationContract]
        void DoStuff();
    }

    public class InstitutionDataService : IInstitutionDataService
    {
        public void DoStuff() { }
    }
}
于 2012-11-08T20:12:35.613 に答える
2

app.config ファイルを使用して自己ホスト型で動作させる方法を次に示します。これは私がよく知っていることなので、私はこのようにしました。必要に応じて、app.config ファイルではなくコードを使用して構成するように変更できます...

using System;
using System.ServiceModel;
using Castle.Facilities.WcfIntegration;
using Castle.MicroKernel.Registration;
using Castle.Windsor;

namespace DISandbox
{
    public class Program
    {
        private static WindsorContainer _container;

        public static void Main(string[] args)
        {
            _container = new WindsorContainer();
            _container.AddFacility<WcfFacility>();

            _container.Register(
                Component
                    .For<IAccountDataService>()
                    .ImplementedBy<AccountDataService>()
                    .AsWcfService(),
                Component
                    .For<IInstitutionDataService>()
                    .ImplementedBy<InstitutionDataService>()
                    .AsWcfService());

            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }
    }

    [ServiceContract]
    public interface IAccountDataService
    {
        [OperationContract]
        void DoStuff();
    }

    public class AccountDataService : IAccountDataService
    {
        public void DoStuff() { }
    }

    [ServiceContract]
    public interface IInstitutionDataService
    {
        [OperationContract]
        void DoStuff();
    }

    public class InstitutionDataService : IInstitutionDataService
    {
        public void DoStuff() { }
    }
}

そして、設定ファイル...

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyHttpServiceBehavior">
          <serviceMetadata httpGetEnabled="True" />
          <serviceDebug includeExceptionDetailInFaults="True" httpHelpPageEnabled="True"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>
      <service name="DISandbox.AccountDataService" behaviorConfiguration="MyHttpServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:49246/AccountDataService"/>
          </baseAddresses>
        </host>
        <endpoint binding="basicHttpBinding" contract="DISandbox.IAccountDataService" />
      </service>

      <service name="DISandbox.InstitutionDataService" behaviorConfiguration="MyHttpServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:49246/InstitutionDataService"/>
          </baseAddresses>
        </host>
        <endpoint binding="basicHttpBinding" contract="DISandbox.IInstitutionDataService" />
      </service>
    </services>
  </system.serviceModel>

</configuration>
于 2012-11-08T16:47:42.363 に答える