【问题标题】:.NET WCF access to local objects.NET WCF 访问本地对象
【发布时间】:2011-01-17 18:24:50
【问题描述】:

我在这篇文章的开头有一个警告。虽然我是一个相当称职的程序员(如果刚从大学毕业 4 年的人就是这种情况),但我对 Windows 编程还是很陌生。我正在使用 .NET C#(第 4 版)进行编程。

我正在尝试创建可以通过“客户端”配置实用程序(Windows 窗体应用程序)远程配置的 Windows 服务。我为 IPC 选择 WCF 的原因是因为我的理解是 WCF 是 Windows Remoting 的替代品,并且 Remoting 正在逐步淘汰。

我的问题是我不知道如何从配置实用程序连接到 Windows 服务时创建的 WCF 实例访问已实例化的对象。

也许这个非常简化的代码块会让您对我正在尝试做的事情有更多的了解。 (边走边编。希望没有令人尴尬的逻辑错误。)

class Blah
{
    /*
     * Create configuration object that is read
     * by myApp and written to by myServ.
    */
    ConfigManager confMan = new ConfigManager();

    MyService myApp = new MyService(ref confMan);
    Thread myAppT = new Thread(new ThreadStart(myApp.init));
    myAppt.Start();
    myAppT.Join();

    //The confServ will handle all of the WCF related stuff
    ConfigServer confServ = new ConfigServer(confMan);
    Thread confServT = new Thread(new ThreadStart(confServ.init));
    confServT.Start();
    confServT.Join();
}

class ConfigManager
{
    public bool someAttribute;

    public ConfigManager()
    {
    }

    public init()
    {
        someAttribute = false;
    }
}

class MyService
{
    ConfigManager confMan;

    public MyService(ref ConfigManager confMan)
    {
        this.confMan = confMan;
    }

    public int init()
    {
        while(1==1)
        {
            if(confMan.someAttribute == true)
                return 0;
        }
    }
}

class ConfServ
{
    ConfigManager confMan;
    public ConfServ(ref ConfigManager confMan)
    {
        this.confMan = confMan;
    }

    public void init()
    {
        //Do all the ServiceHost WCF stuff
    }
}

[ServiceContract]
public interface IModConfig
{
    [OperationContract]
    void changeFalse();
    void changeTrue();
}

/*
 * How can I get my instance of confMan 
 * into this instance of ModConfig
*/
class ModConfig: IModConfig
{
    public void changeFalse()
    {
        /*
         * I want to change confMan.someAttribute
         * to false here.
        */
    }

    public void changeTrue()
    {
        /*
         * I want to change confMan.someAttribute
         * to true here.
        */
    }
}

基本上我只是希望能够写入被 MyService 实例引用的 ConfigManager 实例。

我想我已经清楚地定义了我的问题。如果我需要进一步阐述或改写我的帖子,请告诉我。

【问题讨论】:

  • 我想过打开一个套接字,但这似乎违背了使用 IPC 框架的目的。
  • 线程是怎么回事?将Thread myAppt...myAppT.Join(); 替换为myApp.init();confServer.init 也一样,更容易阅读,更容易调试。

标签: .net wcf windows-services remoting


【解决方案1】:

虽然使用静态字段/属性来存储配置在技术上可以解决这个问题,但我认为这是一种肮脏的黑客行为。你的代码越依赖于静态字段,它的可扩展性就越低(如果在未来的某个时候,你想在一个进程中托管两个相同的服务怎么办?),它对单元测试的抵抗力就变得更大了。

对此的正确解决方案是将InstanceContextMode.Single 与 WCF 框架一起使用,并显式创建您的 WCF 服务实现对象,将其引用传递给它需要的任何核心对象:

MyService app = ...
...

WcfService myService = new WcfService( app );
ServiceHost wcfHost = new ServiceHost( myService );
wcfHost.Open();

...

[ServiceBehavior( InstanceContextMode=InstanceContextMode.Single )]
public class WcfService : IYourWcfContract
{
    private MyService _app;

    public WcfService( MyService app )
    {
        _app = app;
    }

    // Implements IYourWcfContract.UpdateConfiguration
    public void UpdateConfiguration( string newConfig )
    {
        _app.UpdateConfiguration( newConfig );
    }
}

或者,您可以摆脱看似毫无意义的委托,并使用您的MyService 对象作为 WCF 服务实现本身。然而,这也不太理想(在我看来),因为它在MyService 上设置了另一个绑定。

【讨论】:

    【解决方案2】:

    您将配置保存在哪里?

    public void changeTrue()     
    {         
        // load configuration from some file, database, other storage
        // update configuration
        // persist the new configuration
    } 
    

    如果此配置保存在内存中,那么您可以将其设为单例或静态对象,以便只有一个实例。然后,您只需获取单个实例并对其进行修改。

    顺便说一句,while(1==1) 看起来不太对。

    【讨论】:

    • 我现在将它存储在内存中。我喜欢静态对象的想法。只是我想的不对。
    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多