【问题标题】:Object is losing event handlers after being stored / retrieved from Session对象在从 Session 存储/检索后丢失事件处理程序
【发布时间】:2014-09-25 21:34:04
【问题描述】:

类似于DataTable saved to Session state loses event handlers,尽管那里推荐的解决方案不适用。我没有序列化 Session 数据。对象被保存在 InProc 中。

我有一个名为 Application 的类,其中包含以下相关位:

public class Application {
    public event PropertyChangedEventHandler PropertyChanged;

    private Lazy<Asset> _asset;

    public String AssetId { get; set; }

    public Application() {
        RestoreEventHandlers(new StreamingContext());
    }

    [OnDeserialized]
    public void RestoreEventHandlers(StreamingContext context) {
        PropertyChanged += AssetId_PropertyChanged;
        PropertyChanged.Invoke(this, new PropertyChangedEventArgs("AssetId"));
    }

    private void AssetId_PropertyChanged(Object sender, PropertyChangedEventArgs e) {
        if (e.PropertyName == "AssetId")
            _asset = new Lazy<Asset>(() => new Asset(AssetId));
    }

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] String propertyName = null) {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

目标是让_asset 在相关的AssetId 属性更改时重置。我需要保持AssetIdAsset 记录同步。我已验证该事件是在第一次创建对象后调用的。

创建应用程序后,我将其放入 Session 中,如下所示:

HttpContext.Current.Session["CurrentApplication"] = application;

在随后的请求中,我从 Session 中得到它,如下所示:

var application = HttpContext.Current.Session["CurrentApplication"] as Application;

这是从帮助类调用的,这就是为什么我需要使用静态对象来获取当前请求上下文。

稍后,如果用户要求更改应用程序上的资产,我将在同一方法中执行此操作:

application.AssetId = assetId;

在此分配之后,不会调用事件处理程序。如果我这样写,它会按预期工作:

application.RestoreEventHandlers(new StreamingContext());
application.AssetId = assetId;

某事导致我的事件处理程序变得未绑定。有什么想法吗?

【问题讨论】:

  • 最后2个sn-ps的code是一样的,是不是要在最后一个里面放点别的东西?
  • @Rhumborl 是的,很好。对于那个很抱歉。我的意思是,如果我没有明确调用RestoreEventHandlers,那么该事件将不会触发。我不想明确地调用它,因为重点是让客户端代码完全不知道该机制。

标签: c# asp.net-mvc session events


【解决方案1】:

我可能已经离开了这里,但是除了RestoreEventHandlers() 之外,还有没有调用PropertyChanged 事件?我记得你需要在属性内手动提升它 - 参见http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx的示例

private string _assetId;

public string AssetId
{
    get
    {
        return _assetId;
    }
    set
    {
        _assetId = value;
        OnPropertyChanged();
    }
}

当然你也可以重置属性内的_asset

private string _assetId;

public string AssetId
{
    get
    {
        return _assetId;
    }
    set
    {
        _assetId = value;
        _asset = new Lazy<Asset>(() => new Asset(AssetId));
    }
}

【讨论】:

  • 你是对的 - 它根本没有被调用。完美的解决方案,谢谢!
猜你喜欢
  • 2017-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-26
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多