C#:所以如果一个静态类是存储全局状态信息的坏习惯,什么是一个很好的选择,提供了同样的方便? [英] C# : So if a static class is bad practice for storing global state info, what's a good alternative that offers the same convenience?

查看:147
本文介绍了C#:所以如果一个静态类是存储全局状态信息的坏习惯,什么是一个很好的选择,提供了同样的方便?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直注意到静态类在SO上有很多糟糕的代码,用于存储全局信息。 (和一般的全局变量)我只是想知道一个很好的选择是我的例子下面...

I've been noticing static classes getting a lot of bad rep on SO in regards to being used to store global information. (And global variables being scorned upon in general) I'd just like to know what a good alternative is for my example below...

我正在开发一个WPF应用程序和从我的数据库检索的数据的许多视图基于当前登录的用户的ID进行过滤。同样,我应用中的某些点只能访问被认为是管理员的用户。

I'm developing a WPF app, and many views of the data retrieved from my db are filtered based on the ID of the current logged in user. Similarly, certain points in my app should only be accessable to users who are deemed as 'admins'.

我目前正在存储 loggedInUserId 和在静态类中的 isAdmin 布尔。

I'm currently storing a loggedInUserId and an isAdmin bool in a static class.

我的应用程序的各个部分需要这个信息,我想知道为什么它不是理想的case,和什么替代品。

Various parts of my app need this info and I'm wondering why it's not ideal in this case, and what the alternatives are. It seems very convienient to get up and running.

我可以想到的另一个选择是使用IoC容器来注入一个Singleton实例到需要这个全局信息,类可以通过它的接口与此通信。

The only thing I can think of as an alternative is to use an IoC Container to inject a Singleton instance into classes which need this global information, the classes could then talk to this through its interface. However, is this overkill / leading me into analysis paralysis?

提前感谢任何洞察力。

更新

所以我倾向于通过IoC进行依赖注入,因为它会更好地可测试性,因为我可以交换一个服务,提供全球信息与模拟,如果需要。我想假设剩下的是注入的对象应该是单例还是静态的。 : - )

So I'm leaning towards dependency injection via IoC as It would lend itself better to testability, as I could swap in a service that provides "global" info with a mock if needed. I suppose what remains is whether or not the injected object should be a singleton or static. :-)

将会挑选Mark的回答,虽然等待看看有没有更多的讨论。我不认为有一个正确的方式。我只是有兴趣看到一些讨论,这将启发我,因为似乎有很多这是坏的这是坏的一些类似的问题,没有任何建设性的选择的声明。

Will prob pick Mark's answer although waiting to see if there's any more discussion. I don't think there's a right way as such. I'm just interested to see some discussion which would enlighten me as there seems to be a lot of "this is bad" "that is bad" statements on some similar questions without any constructive alternatives.

更新#2
所以我选择了Robert的回答,因为这是一个很好的选择词,可能是一个真正的方式看到,因为它被内置到框架)。这不是强制我创建一个静态类/单例(虽然它是线程静态)。

Update #2 So I picked Robert's answer seeing as it is a great alternative (I suppose alternative is a weird word, probably the One True Way seeing as it is built into the framework). It's not forcing me to create a static class/singleton (although it is thread static).

唯一仍然让我好奇的是如何解决如果我必须存储的全局数据与用户验证无关。

The only thing that still makes me curious is how this would have been tackled if the "global" data I had to store had nothing to do with User Authentication.

推荐答案

忘记单例和静态数据。

Forget Singletons and static data. That pattern of access is going to fail you at some time.

创建您自己的自定义IPrincipal,并在适当的登录点替换Thread.CurrentPrincipal。通常保存对当前IIdentity的引用。

Create your own custom IPrincipal and replace Thread.CurrentPrincipal with it at a point where login is appropriate. You typically keep the reference to the current IIdentity.

在用户登录的例程中,您已验证其凭据,将您的自定义主体附加到主题。

In your routine where the user logs on, e.g. you have verified their credentials, attach your custom principal to the Thread.

IIdentity currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
System.Threading.Thread.CurrentPrincipal 
   = new MyAppUser(1234,false,currentIdentity);

您还将设置 HttpContext.Current.User

public class MyAppUser : IPrincipal
{
   private IIdentity _identity;

   private UserId { get; private set; }
   private IsAdmin { get; private set; } // perhaps use IsInRole

   MyAppUser(userId, isAdmin, iIdentity)
   {
      if( iIdentity == null ) 
         throw new ArgumentNullException("iIdentity");
      UserId = userId;
      IsAdmin = isAdmin;
      _identity = iIdentity;          
   }

   #region IPrincipal Members
   public System.Security.Principal.IIdentity Identity
   {
      get { return _identity; }
   }

   // typically this stores a list of roles, 
   // but this conforms with the OP question
   public bool IsInRole(string role)
   {  
      if( "Admin".Equals(role) )
         return IsAdmin;     

      throw new ArgumentException("Role " + role + " is not supported");
   }
   #endregion
}

做到这一点,它在框架中有一个原因。

This is the preferred way to do it, and it's in the framework for a reason. This way you can get at the user in a standard way.

如果用户是匿名的(未知),我们还可以添加属性,以支持混合匿名方案/登录的身份验证方案。

We also do things like add properties if the user is anonymous (unknown) to support a scenario of mixed anonymous/logged-in authentication scenarios.

此外:


  • DI(依赖注入),通过注入检索/检查凭据的成员资格服务。

  • 您可以使用Repository模式来获得对当前MyAppUser的访问权限(尽管可以说它只是为您的MyAppUser进行转换),

这篇关于C#:所以如果一个静态类是存储全局状态信息的坏习惯,什么是一个很好的选择,提供了同样的方便?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆