从Session存储/检索后,对象正在丢失事件处理程序

时间:2014-09-25 13:01:18

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

DataTable saved to Session state loses event handlers类似,但推荐的解决方案并不适用。我没有序列化会话数据。对象被保存在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;

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

1 个答案:

答案 0 :(得分:2)

我可能会离开这里,但PropertyChanged事件除了在RestoreEventHandlers()之外被调用了吗?我记得你需要在属性中手动提升它 - 参见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));
    }
}