为了账号安全,请及时绑定邮箱和手机立即绑定

我该如何正确地将`TempDataDictionary`注入我的班级?

我该如何正确地将`TempDataDictionary`注入我的班级?

C#
海绵宝宝撒 2021-05-14 17:12:55
我有一个使用c#和ASP.NET MVC 5编写的应用程序。我还使用Unity.Mvc进行依赖项注入。与许多其他类一起,该类MessageManager在IoC容器中注册。但是,MessageManager该类依赖于的实例TempDataDictionary来执行其工作。此类用于为视图写入临时数据。为了解析的实例,MessageManager我还需要注册的实例TempDataDictionary。我将需要能够TempDataDictionary从MessageManager类中添加值,然后需要从视图访问临时数据。因此,我需要能够访问TempDataDictionary视图中的相同实例,以便可以将消息写给用户。另外,如果控制器将用户重定向到其他地方,我也不想丢失消息,但我仍然希望能够在下一个视图中显示该消息。我尝试了以下方法来注册TempDataDictionary和MessageManager:Container.RegisterType<TempDataDictionary>(new PerThreadLifetimeManager())         .RegisterType<IMessageManager, MessageManager>();然后,在我看来,我有以下解决方案来解决 IMessageManagervar manager = DependencyResolver.Current.GetService<IMessageManager>();但是,该消息由于某种原因而丢失。也就是说,当我解析时manager,TempDataDictionary不包含MessageManager从控制器添加的任何消息。如何正确注册的实例,TempDataDictionary以便数据一直保留到被查看?更新 这是我的IMessageManager界面public interface IMessageManager{    void AddSuccess(string message, int? dismissAfter = null);    void AddError(string message, int? dismissAfter = null);    void AddInfo(string message, int? dismissAfter = null);    void AddWarning(string message, int? dismissAfter = null);    Dictionary<string, IEnumerable<FlashMessage>> GetAlerts();}
查看完整描述

2 回答

?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

该TempDataDictionary是你的内在组成部分MessageManager执行情况,因此,你应该实现它是类里面,而不是直接在容器中对其进行注册的。


就像是:


public class MessageManager : IMessageManager

{

    private TempDataDictionary _tempDataDictionary;


    [...]

}

但是,恕我直言,我认为TempDataDictionary在控制器上下文之外使用不是一个好习惯,因此,您可以在每次添加或检索消息时通过它,而不是在您的类中实现它:


void AddSuccess(IDictionary<string, object> tempData, string message);

您还可以MessageManager使用来为每个请求创建一个实例PerThreadLifetimeManager,然后根本不需要使用TempDataDictionary,只需使用常规列表或字典自己实现即可:


public class MessageManager : IMessageManager

{

    private List<string> _successMessages = new List<string>();

    private List<string> _errorMessages = new List<string>();

    private List<string> _warningMessage = new List<string>();

    private List<string> _infoMessage = new List<string>();


    public void AddSuccess(string message)

    {

        _successMessages.Add(message);

    }


    public void AddError(string message)

    {

        _errorMessages.Add(message);

    }


    public void AddWarning(string message)

    {

        _warningMessages.Add(message);

    }


    public void AddInfo(string message)

    {

        _infoMessages.Add(message);

    }


    public List<string> SuccessMessages

    {

        get { return _successMessages; }

    }


    public List<string> ErrorMessages

    {

        get { return _errorMessages; }

    }


    public List<string> WarningMessages

    {

        get { return _warningMessages; }

    }


    public List<string> InfoMessages

    {

        get { return _infoMessages; }

    }

}

然后,为每个线程注册它,以便在每个请求中清除所有内容:


Container.RegisterType.RegisterType<IMessageManager, MessageManager>

        (new PerThreadLifetimeManager());

更好的方法?


如果要确保列表一直保留到读取为止,即使它在另一个请求中发生,或者如果您正在使用异步操作或ajax请求,则可以创建自己的LifetimeManager实现来解析上述类的实例。每个会话,例如:


public class SessionLifetimeManager : LifetimeManager

{

    private string _key = Guid.NewGuid().ToString();

    public override void RemoveValue(ILifetimeContainer container = null)

    {

        HttpContext.Current.Session.Remove(_key);

    }

    public override void SetValue(object newValue, ILifetimeContainer container = null)

    {

        HttpContext.Current.Session[_key] = newValue;

    }

    public override object GetValue(ILifetimeContainer container = null)

    {

        return HttpContext.Current.Session[_key];

    }

    protected override LifetimeManager OnCreateLifetimeManager()

    {

        return new PerSessionLifetimeManager();

    }

}

然后PerThreadLifetimeManager,SessionLifetimeManager在上方替换为,并在每次访问该列表时都将其清除,例如:


public List<string> InfoMessages

{

    get 

    { 

         // Some view has accessed the data, clear the list before returning

         var tempInfoMessages = new List<string>(_infoMessages);

         _infoMessages.Clear();

         return tempInfoMessages; 

    }

}


查看完整回答
反对 回复 2021-05-21
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

严格来说,这不是答案,而是另一种建议:


另外,如果控制器将用户重定向到其他地方,我也不想丢失消息,但我仍然希望能够在下一个视图中显示该消息。


仅仅看一下上面的内容,对我来说,将您的消息存储在数据库中可能是一个更好的选择。这样,您甚至可以返回过去并根据需要查看旧消息。


// persist in EF db context

class Message {

    DateTime CreatedUtc { get; set; }

    DateTime SeenUtc { get; set; }

    string Text { get; set; }

    AspNetUser User { get; set; }

    // etc

}

然后,您可以在请求中保留该消息,管理何时将该消息标记为已看到,甚至让用户看到他的旧消息(如果您愿意的话)


查看完整回答
反对 回复 2021-05-21
  • 2 回答
  • 0 关注
  • 145 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信