2012-08-23 56 views
2

我想在创建过程中将对象传递给WCF服务 - 'MasOperationsService'。 但我遇到一个错误,我无法弄清楚为什么。在WCF服务构造函数中发送参数 - 错误

我想这件code from here ...

[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; 
    } 
+0

什么错误? –

+0

我不确定你想要做什么,但如果所有这些的最终目的是让你的自定义头部的值在任何服务实现方法中可用,那么最好使用基类作为你的方法输入参数使用'MessageContract'而不是'Datacontract'。 – Paciv

回答

0

你的问题是,你设置InstanceContextMode = InstanceContextMode.Single。 此模式指定跨所有服务请求使用单个服务实例。 在这种情况下,WCF框架在您实例化ServiceHost的那一刻实例化您的服务的单例实例,甚至在甚至可以尝试插入自定义InstanceProvider并将对所有后续请求使用同一实例。

我不确定你要做什么,但如果所有这些的最终目的是让你的自定义头部的值在任何服务实现方法中可用,那么最好使用基类您的方法使用MessageContract而不是Datacontract输入参数。

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

我想要实现的很简单。我有一个命令行应用程序 - MyCmdApp。 MyCmdApp将使用WCF服务侦听客户端请求。这个应用程序然后将客户端请求委托给另一个名为MyServerApp的应用程序。 WCF服务*必须*使用称为MyProxy的类委托来自客户端的调用。当启动MyCmdApp时,需要启动MyProxy。我需要以这样的方式创建应用程序,WCF应该引用MyProxy实例,该实例已启动。 –

+0

你的名字参数是kickstart参数吧?如果是这样的话,它可以在MyCmdApp中使用,无论是服务器端还是主机/第一个呼叫端,您都不需要所有这些,只需执行服务中的kickstart即可。 – Paciv