在WCF服务构造函数中发送参数 - 错误

时间:2012-08-23 15:17:11

标签: c# wcf constructor initialization

我正在尝试在创建期间将对象传递给WCF服务 - 'MasOperationsService'。 但我遇到了一个错误,我无法弄清楚原因。

我正在尝试这段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;
    }

2 个答案:

答案 0 :(得分: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();  
    }
}

答案 1 :(得分:-1)

默认情况下,WCF使用无参数构造函数。为了使用其他构造函数,您应该实现IInstanceProvider接口。

您可以参考以下问题。

How do I pass values to the constructor on my wcf service?