Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在使用.NET远程处理时只能从ASP.NET web app读取属性而不能设置属性?_C#_Asp.net_Remoting_.net Remoting - Fatal编程技术网

C# 为什么在使用.NET远程处理时只能从ASP.NET web app读取属性而不能设置属性?

C# 为什么在使用.NET远程处理时只能从ASP.NET web app读取属性而不能设置属性?,c#,asp.net,remoting,.net-remoting,C#,Asp.net,Remoting,.net Remoting,我在尝试设置Windows服务中托管的远程对象的属性时遇到问题。我试图更改对象的属性,但由于某种原因,它没有保存 以下是服务的相关代码: private static List<Alert> _alerts = new List<Alert>(); // List of the Alerts private TcpChannel _tcpChannel; protected override void OnStart(string[] args)

我在尝试设置Windows服务中托管的远程对象的属性时遇到问题。我试图更改对象的属性,但由于某种原因,它没有保存

以下是服务的相关代码:

    private static List<Alert> _alerts = new List<Alert>(); // List of the Alerts
    private TcpChannel _tcpChannel;

    protected override void OnStart(string[] args)
    {
        loadAlerts(); // This sets up the List (code not req'd)
        // Set up the remotelister so that other processes can access _alerts
        // Create the TcpChannel
        _tcpChannel = new TcpChannel(65000);
        ChannelServices.RegisterChannel(_tcpChannel, false);

        // Register the Proxy class for remoting.
        RemotingConfiguration.RegisterWellKnownServiceType(
          typeof(RemoteLister),
          "AlertList.soap",
          WellKnownObjectMode.Singleton);
    }

    [Serializable]
    public class RemoteLister : MarshalByRefObject
    {
        public List<Alert> TheList
        {
            get { return _alerts; }
            set { _alerts = value; }
        }

        public bool save()
        {
            EventLog.WriteEntry("AlertService", "Calling saveAlerts...");
            return saveAlerts();
        }
    }
现在,在我的ASP.NET web应用程序中,以下是我初始化所有内容的方式:

AlertService.RemoteLister remoteAlertList;

    protected void Page_Load(object sender, EventArgs e)
    {
        // This is where we create a local object that accesses the remote object in the service
        Type requiredType = typeof(AlertService.RemoteLister);
        // remoteAlertList is our reference to the List<Alert> in the always running service
        remoteAlertList = (AlertService.RemoteLister)Activator.GetObject(requiredType,
                "tcp://localhost:65000/AlertList.soap");
    }
但是,当我像下面那样更改该属性时,它不起作用

 protected void AlertSaveButton_Click(object sender, EventArgs e)
    {
        remoteAlertList.TheList[AlertDropDownList.SelectedIndex].AlertName = AlertNameTextBox.Text;
    }
有人知道为什么它不能挽救那笔财产吗

提前谢谢

我猜,由于
列表
不是从
MarshalByRefObject
继承的,当您调用属性
remoteAlertList时,列表
会得到一个断开连接的对象。或许可以将索引器添加到对象:

public class RemoteLister : MarshalByRefObject
{
    public Alert this[int index] {get {...} set {...}}
}
实际上,我主要想说的是沟渠远程处理和使用WCF/SOA。而
RemoteLister
成为
[可序列化]
的目的也不大。您可能还需要考虑线程安全性


澄清;
警报
实例也将是独立的,因此本地更新不会影响服务器;基本上,您有两种情况:

  • 如果类型为
    MarshalByRefObject
    ,则它仅存在于服务器上;所有客户端操作都远程到实际对象,但对于
    MarshalByRefObjecf
    类型,仅远程
  • 否则,将序列化对象并重构实际对象
如果您使用索引器(例如)

那么这就是:

var tmp = obj[index]; // tmp points to the deserialized disconnected Alert
tmp.Name = "abc"; // we update the local disconnected Alert
(如果
Alert
MarshallByRefObject
,这将更新服务器,但不执行此操作)。但如果我们将价值推后:

然后我们更新了服务器


正如您所发现的,以操作为中心的设计可能要简单得多(即
setAlertName
)。但是我确实认为远程处理在这里是个坏主意。

尝试了索引器,但没有成功。我尝试了下面所示的另一种方法,效果很好,但这似乎是一种解决方法,而不是正确的方法。我所做的只是在RemoteLister类中添加了以下内容:

public void setAlertName(int index, string name)
            {
                _alerts[index].AlertName = name;
            }
然后将“保存”按钮更改如下:

protected void AlertSaveButton_Click(object sender, EventArgs e)     
{     
    remoteAlertList.setAlertName(AlertDropDownList.SelectedIndex, AlertNameTextBox.Text);    
} 

我想这将暂时解决我的问题,但如果有人知道为什么我第一次使用时它不起作用,我宁愿使用“正确”的方法。我已经查看了您的代码,它似乎是正确的。 但可能导致错误的代码行位于remoteAlertList中:

    remoteAlertList = (AlertService.RemoteLister)Activator.GetObject(requiredType, "tcp://localhost:65000/AlertList.soap");
您已经使用初始.net转换方法“(newType)obj”和Activator.GetObject(..)初始化了remoteAlertList类,其中一个不会返回原始obj的引用[我认为是Activator.GetObject(..)]。它返回“AlertService.RemoteLister”类的精确副本,因此当您调用“TheList”时,您调用了它的精确副本,当您调用Save()时,它保存在复制的对象中,而不是真实的对象中


在这里,我看不到您的完整代码,但从我看到的情况来看,我可以告诉您,解决方案是找到从主机访问AlertService.RemoteLister对象引用的方法。

尝试作为索引器执行此操作。。。不走运。关于可序列化的建议,马克-你是对的,它没有任何用途。我是C#的新手,刚开始访问它时遇到了错误,说它需要可序列化,所以我在这里和实际的Alert类中添加了[serializable],它成功了。我想我只需要在警觉课上用它。至于线程安全,好主意。虽然它可能不会一次被多个线程访问,但这是可能的,我将对此进行研究。为什么你认为远程处理是个坏主意?这似乎是实现这一点的最简单方法。。。我简单地研究了一下WCF,它似乎有很多额外的工作和开销。windows服务和web应用在同一台服务器上,如果这有区别的话。我正在学习,我想用“最好”的方式来做这件事,所以我真的很有兴趣听听你关于如何做这件事的建议。WCF其实并不比远程处理更难设置(也没有更多的开销)。在很多方面都比较简单。如果远程处理对您有效,那么很好。事实上,不必导航防火墙使事情变得更简单。总的来说,我相信WCF有更多的灵活性,但如果你不需要它。。。(毕竟,我没有拒绝回答远程问题)。也许把它当作“也考虑WCF”,这听起来像你已经做了……我补充了一些进一步的解释,你的评论只是一个FIY…一个免费的工具来帮助你做的事情“正确”的方式是FxCop。它会分析您的代码,并推荐VisualStudio不会推荐的内容。例如,它会告诉您不要通过属性公开泛型列表。相反,使用索引器来设置项,并为get公开一个只读列表。这允许您控制添加到列表中的内容和时间。如果您公开它,任何使用您的类的东西都可以随时改变它的状态。只是一些想法。谢谢亚伦,我会查出来的!我真的很感谢董事会的帮助!
obj[index] = tmp;
public void setAlertName(int index, string name)
            {
                _alerts[index].AlertName = name;
            }
protected void AlertSaveButton_Click(object sender, EventArgs e)     
{     
    remoteAlertList.setAlertName(AlertDropDownList.SelectedIndex, AlertNameTextBox.Text);    
} 
    remoteAlertList = (AlertService.RemoteLister)Activator.GetObject(requiredType, "tcp://localhost:65000/AlertList.soap");