2

作成中に WCF サービスにオブジェクトを渡そうとしています - 「MasOperationsService」。しかし、エラーが発生し、その理由がわかりません。

ここからこのコードを試しています...

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
public class MasOperationsService : IMasOperations
{
    public MasOperationsService()
        : this("INVALID")  
    {  
        throw new InvalidOperationException("This should never be called");  
    }  

    public MasOperationsService(string name)
    {

    }

    //public CoAuthorSearchResult ExtractCoAuthorsFromAuthor(long AuthorCellId, uint LevelsToExtract)
    //{
    //    //throw new NotImplementedException("Running This At Proxy, This should now query Slaves!!");
    //    return new CoAuthorSearchResult();
    //}
}

public class MyInstanceProvider : IInstanceProvider
{
    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        string name = message.Headers.GetHeader<string>("Name", "http://my.namespace");
        if (name != null)
        {
            return new MasOperationsService("Service " + name);
        }
        else
        {
            return new MasOperationsService("Service with no name");
        }
    }
    public object GetInstance(InstanceContext instanceContext)
    {
        return new MasOperationsService("Service with no name");
    }
    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
    }
}
public class MyServiceBehavior : IServiceBehavior
{
    MyInstanceProvider myProvider = new MyInstanceProvider();
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher ed in cd.Endpoints)
            {
                ed.DispatchRuntime.InstanceProvider = this.myProvider;
            }
        }
    }
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
}

MasOperationsService() はサービス クラスです。クライアント コードは LaunchWcfService() です。

public void LaunchWcfService()
    {
        string baseAddress = "http://localhost:8733/Design_Time_Addresses/MASService/Service1";
        ServiceHost host = new ServiceHost(typeof(MasOperationsService), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(IMasOperations), GetBinding(), "");
        host.Description.Behaviors.Add(new MyServiceBehavior());
        host.Open();
        Console.WriteLine("Host opened");

        ChannelFactory<IMasOperations> factory = new ChannelFactory<IMasOperations>(GetBinding(), new EndpointAddress(baseAddress));
        IMasOperations proxy = factory.CreateChannel();

        using (OperationContextScope scope = new OperationContextScope((IContextChannel)proxy))
        {
            OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("Name", "http://my.namespace", "Name 1"));
            //Console.WriteLine(proxy.Hello("foo"));
            OperationContext.Current.OutgoingMessageHeaders.RemoveAll("Name", "http://my.namespace");
            OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("Name", "http://my.namespace", "Name 2"));
            //Console.WriteLine(proxy.Hello("bar"));
        }

        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();  
    }

    static Binding GetBinding()
    {
        BasicHttpBinding result = new BasicHttpBinding();
        return result;
    }
4

2 に答える 2

0

あなたの問題は、あなたが設定したことですInstanceContextMode = InstanceContextMode.Single。このモードは、すべてのサービス リクエストで単一のサービス インスタンスを使用するように指定します。この場合、WCF フレームワークは、ServiceHost をインスタンス化した時点で、サービスのシングルトン インスタンスをインスタンス化し、カスタム InstanceProvider をプラグインして後続のすべての要求にこの同じインスタンスを使用する前にインスタンス化します。

あなたが何をしようとしているのかはわかりませんが、これらすべての最終目的が、カスタムヘッダーの値をサービス実装メソッド内で利用できるようにすることである場合は、メソッドの入力パラメーターに基本クラスを使用することをお勧めしますDatacontract の代わりに MessageContract を使用します。

[ServiceContract]
public interface IMasOperations
{
    [OperationContract]
    CoAuthorSearchResult ExtractCoAuthorsFromAuthor(ExtractCoAuthorsFromAuthorRequest request);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MasOperationsService : IMasOperations
{    
    public CoAuthorSearchResult  ExtractCoAuthorsFromAuthor(ExtractCoAuthorsFromAuthorRequest request)
    {
        Console.WriteLine("Name header accessed inside WS implementation though request.Name. Value = {0}.", request.Name);
        return new CoAuthorSearchResult();
    }
}

[MessageContract]
public class BaseRequest
{
    [MessageHeader]
    public string Name { get; set; }
}

[MessageContract]
public class ExtractCoAuthorsFromAuthorRequest : BaseRequest
{
    [MessageBodyMember]
     public long AuthorCellId { get; set; }

    [MessageBodyMember]
    public uint LevelsToExtract { get; set; }
}

[MessageContract]
public class CoAuthorSearchResult { }

public class Program
{
    static readonly Binding _binding = new BasicHttpBinding();

    public static void Main(string[] args)
    {
        string baseAddress = "http://localhost:8733/Design_Time_Addresses/MASService/Service1";
        ServiceHost host = new ServiceHost(typeof(MasOperationsService), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(IMasOperations), _binding, string.Empty);
        host.Open();
        Console.WriteLine("Host opened");

        ChannelFactory<IMasOperations> factory = new ChannelFactory<IMasOperations>(_binding, new EndpointAddress(baseAddress));
        IMasOperations channel = factory.CreateChannel();

        CoAuthorSearchResult result = channel.ExtractCoAuthorsFromAuthor(new ExtractCoAuthorsFromAuthorRequest
        {
            Name = "http://my.namespace",
            AuthorCellId = 0,
            LevelsToExtract = 1,
        });


        ICommunicationObject o = channel as ICommunicationObject;
        if (o != null)
        {
            if (o.State == CommunicationState.Opened)
            {
                o.Close();
            }
            else
            {
                o.Abort();
            }
        }

        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();  
    }
}
于 2012-08-23T16:27:33.233 に答える
-1

既定では、WCF はパラメーターなしのコンストラクターを使用します。別のコンストラクターを使用するには、インターフェイスを実装する必要がありIInstanceProviderます。

次の質問を参照できます。

wcf サービスのコンストラクターに値を渡すにはどうすればよいですか?

于 2012-08-23T15:23:03.137 に答える