如何为没有SVC文件的自托管WCF服务指定ServiceHostFactory

时间:2015-04-23 13:50:27

标签: c# wcf self-hosting servicehost was

我的应用程序作为Windows服务运行。它使用以下帮助程序方法动态创建WCF服务:

- (void)rotate {
    NSInteger left = self.Left;
    NSInteger middle = self.Middle;
    NSInteger right = self.Right;
    self.Left = middle;
    self.Middle = right;
    self.Right = left;

    //this works 
    //_baseLayer.transform = CATransform3DConcat(_baseLayer.transform, CATransform3DMakeRotation(degreesToRadians(120), 0,0,1));

    //rotate with pop, at some point this starts to rotate more than 120
    POPSpringAnimation *rotateAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerRotation];
    rotateAnimation.toValue = @([rotateAnimation.fromValue floatValue] + 120/360.0f*(2*M_PI));
    rotateAnimation.springBounciness = 10.0f;
    rotateAnimation.springSpeed = 25.0f;        
    [_baseLayer pop_removeAnimationForKey:@"kAnimationRotate"];
    [_baseLayer pop_addAnimation:rotateAnimation forKey:@"kAnimationRotate"];
}

- (void)flipUpDown {
    _baseLayer.transform = CATransform3DConcat(_baseLayer.transform, CATransform3DMakeRotation(M_PI, 1.0f, 0, 0));        
}

- (void)flipLeftRight {
    NSInteger left = self.Left;
    NSInteger right = self.Right;
    self.Left = right;
    self.Right = left;

    _baseLayer.transform = CATransform3DConcat(_baseLayer.transform, CATransform3DMakeRotation(M_PI, 0, 1.0f, 0));
}

这些服务没有.SVC文件。还要明确的是,这些是自托管服务,不在IIS下运行 - 它们在WAS(Windows激活服务)下运行。

现在我想控制实现类的实例化方式。听起来这可以完成with a ServiceHostFactory。但是我发现所有关于这个的文章都说明了指定使用什么工厂的方法是将类型名称放在.SVC文件的@ServiceHost指令中。我没有这个文件!

有没有办法在没有在WAS下运行的SVC文件的情况下将我自己的ServiceHost工厂用于WCF服务?

更新以下答案

这是我的新辅助方法,结合了Carlos的解决方案

    public static void StartWebService(string webServiceName, Type serviceContractType, Type serviceImplementationType)
    {
        if (string.IsNullOrEmpty(webServiceName)) return;

        var baseAddress = GetWebServiceAddress(webServiceName);
        var baseUri = new Uri(baseAddress);

        lock (RunningWebServices)
        {
            if (RunningWebServices.ContainsKey(webServiceName))
                return;

            var webServiceHost = new ServiceHost(serviceImplementationType, baseUri);

            var serviceBehaviour = new ServiceMetadataBehavior() { HttpGetEnabled = true };
            webServiceHost.Description.Behaviors.Add(serviceBehaviour);
            webServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

            var httpBinding = new BasicHttpBinding();
            webServiceHost.AddServiceEndpoint(serviceContractType, httpBinding, baseAddress);
            webServiceHost.Open();

            RunningWebServices.Add(webServiceName, webServiceHost);
        }
    }

1 个答案:

答案 0 :(得分:3)

您不需要服务主机工厂来控制如何实例化服务实现类 - 您需要通过使用自定义服务行为向调度运行时添加IInstanceProviderhttp://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx上的博客文章详细介绍了如何实现这一目标。例如,下面的SSCCE显示了如何使用实例提供程序的示例(对于没有默认构造函数的服务,因此在WCF中不能直接使用,没有实例提供程序)

public class StackOverflow_29825519
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        string WhoAmI();
    }
    public class Service : ITest
    {
        string name;

        public Service(string name)
        {
            this.name = name;
        }

        public string WhoAmI()
        {
            return this.name;
        }
    }
    class MyBehavior : IServiceBehavior, IInstanceProvider
    {
        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;
                }
            }
        }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return this.GetInstance(instanceContext);
        }

        public object GetInstance(InstanceContext instanceContext)
        {
            return new Service("John Doe");
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
        host.Description.Behaviors.Add(new MyBehavior());
        host.Open();
        Console.WriteLine("Host opened");

        ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
        ITest proxy = factory.CreateChannel();
        Console.WriteLine("WhoAmI: {0}", proxy.WhoAmI());

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

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