我们可以将工作流服务作为Windows服务托管吗? [英] Can we host a Workflow Service as a Windows Service?

查看:57
本文介绍了我们可以将工作流服务作为Windows服务托管吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个日志记录应用程序,该应用程序要求我具有作为服务公开的工作流(工作流服务).我们希望将其托管为Windows服务(不想将工作流服务托管为IIS中的.svc文件).将其作为Windows服务的另一个原因是能够通过命名管道与该服务进行通信.

I am working on a logging application that requires me to have a Workflow that is exposed as a Service (Workflow Service). We want to host it as a Windows Service (don't want to host workflow service as .svc file in IIS). Another reason for having it as windows service is to be able to communicate with the service through the Named pipes.

是否可以通过命名管道公开工作流服务而不将其托管在IIS中?

Can we expose a Workflow Service through Named Pipes without hosting it in IIS?

推荐答案

是的,请确定.至少,我在Workflow 4 Release Candidate方面已经完成了很多工作.

Yep bep, you sure can. At least, I have accomplished as much with Workflow 4 Release Candidate.

考虑

// a generic self-hosted workflow service hosting thingy. Actual
// implementation should contain more logging and thread safety, this
// is an abbreviated version ;)
public class WorkflowHost
{

    // NOTE: with Workflow, it helps to maintain a concept of
    // Workflow definition [the Activity or WorkflowService from
    // a designer] and a Workflow instance [what is running within
    // WorkflowInvoker, WorkflowApplication, WorkflowServiceHost].
    // a definition may be used to generate an instance. an instance
    // contains run-time state and cannot be recycled into a new
    // instance. therefore, to repeatedly re-host a WorkflowService
    // we need to maintain references to original definitions and
    // actual instances. ergo services and hosts maps
    // 
    // if you are special purpose and require support for one and 
    // only one service and endpoint\uri, then you may reduce this 
    // to a simple tuple of Uri, WorkflowService, WorkflowServiceHost

    // services represents a definition of hosted services
    private readonly Dictionary<Uri, WorkflowService> _services = 
        new Dictionary<Uri, WorkflowService> ();

    // hosts represents actual running instances of services
    private readonly Dictionary<Uri, WorkflowServiceHost> _hosts = 
        new Dictionary<Uri, WorkflowServiceHost> ();

    // constructor accepts a map of Uris (ie service endpoints) to
    // workflow service definitions
    public WorkflowHost (IDictionary<Uri, WorkflowService> services)
    {
        foreach (KeyValuePair<Uri, WorkflowService> servicePair in services)
        {
            _services.Add (servicePair.Key, servicePair.Value);
        }
    }

    // have your windows service invoke this to start hosting
    public void Start ()
    {
        if (_hosts.Count > 0)
        {
            Stop ();
        }

        foreach (KeyValuePair<Uri, WorkflowService> servicePair in _services)
        {
            WorkflowService service = servicePair.Value;
            Uri uri = servicePair.Key;
            WorkflowServiceHost host = new WorkflowServiceHost (service, uri);

            host.Open ();

            _hosts.Add (uri, host);
        }
    }

    // have your windows service invoke this to stop hosting
    public void Stop ()
    {
        if (_hosts.Count > 0)
        {
            foreach (KeyValuePair<Uri, WorkflowService> servicePair in 
                _services)
            {
                WorkflowService service = servicePair.Value;
                Uri uri = servicePair.Key;

                IDisposable host = _hosts[uri];
                host.Dispose ();
            }

            _hosts.Clear ();
        }
    }
}

我相信可以通过App.config中的标准Wcf服务配置部分来设置端点配置.在使用Workflow进行实验时,我还没有亲自尝试更改默认传输层.

I believe endpoint configuration may be set via standard Wcf service configuration sections in App.config. I have not personally attempted a change to default transport layer in my experiments with Workflow.

以上内容代表一个通用的纯托管类[即,它自托管WorkflowServices].这使我们可以在控制台,WinForm,WPF或什至是WindowsService应用程序中重用此托管功能.下面是利用我们的主机类的WindowsService

The above represents a generic pure hosting class [ie it self-hosts WorkflowServices]. This allows us to re-use this hosting functionality within a console, WinForm, WPF, or yes, even a WindowsService application. Below is a WindowsService that leverages our host class

// windows service. personally i would abstract service behind
// an interface and inject it, but again, for brevity ;)
public partial class WorkflowWindowsService : ServiceBase
{
    WorkflowHost _host;

    public WorkflowWindowsService ()
    {
        InitializeComponent();

        Dictionary<Uri, WorkflowService> services = 
            new Dictionary<Uri, WorkflowService> ();

        // do your service loading ...

        // create host
        _host = new WorkflowHost (services);
    }

    protected override void OnStart(string[] args)
    {
        _host.Start ();
    }

    protected override void OnStop()
    {
        _host.Stop ();
    }
}

如果您在VS2010RC中摆弄了WorkflowServices,那么您可能已经知道WorkflowServices并不是它们的Workflow表亲之类的一流Xaml类.而是将它们另存为扩展名为.xamlx的Xaml文件. [据我所知]不存在对WorkflowServices的设计时智能感知支持,并且不被识别为声明的类型,因此,在运行时加载WorkflowService的唯一选择是

If you have fiddled with WorkflowServices in VS2010RC, then you may already know that WorkflowServices are not first class Xaml classes like their Workflow cousins. Instead, they are saved as loose Xaml files with the .xamlx extension. There is no design-time intellisense support for WorkflowServices [as far as I know] and are not recognized as declared types, so our only options to load a WorkflowService at run-time are

  • 直接从.xamlx文件读取纯Xaml标记
  • 从其他来源[嵌入的字符串,资源或其他来源]中读取纯Xaml标记

无论哪种方式,我们都必须解释标记并创建WorkflowService定义.下面的代码会将字符串[可以是文件名或标记]转换为WorkflowService. Keeners可能还注意到,此过程与将工作流标记转换为工作流定义的过程之间存在差异.

Either way, we must interpret markup and create a WorkflowService definition. The following will transform a string [that may be a filename or markup] into a WorkflowService. Keeners may also note that there is a difference between this process and the process for transforming Workflow markup to Workflow definitions.

// converts a string value [either pure xaml or filename] to a
// WorkflowService definition
public WorkflowService ToWorkflowService (string value)
{
    WorkflowService service = null;

    // 1. assume value is Xaml
    string xaml = value;

    // 2. if value is file path,
    if (File.Exists (value))
    {
        // 2a. read contents to xaml
        xaml = File.ReadAllText (value);
    }

    // 3. build service
    using (StringReader xamlReader = new StringReader (xaml))
    {
        object untypedService = null;

        // NOTE: XamlServices, NOT ActivityXamlServices
        untypedService = XamlServices.Load (xamlReader);

        if (untypedService is WorkflowService)
        {
            service = (WorkflowService)(untypedService);
        }
        else
        {
            throw new ArgumentException (
                string.Format (
                "Unexpected error reading WorkflowService from " + 
                "value [{0}] and Xaml [{1}]. Xaml does not define a " + 
                "WorkflowService, but an instance of [{2}].", 
                value, 
                xaml, 
                untypedService.GetType ()));
        }
    }

    return service;
}

这篇关于我们可以将工作流服务作为Windows服务托管吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆