简体   繁体   English

C#非永久性“静态”关键字?

[英]C# non-persistent `static` keyword?

I come from a C/C++ background and am having trouble doing some things in C#. 我来自C / C ++背景,在使用C#做某些事情时遇到了麻烦。 My problem right now is that I need a static keyword that works like in C++. 我现在的问题是我需要一个static关键字,其工作方式类似于C ++。 So that the property is global to all instances of the class, which is what C#'s does. 这样该属性对于该类的所有实例都是全局的,这就是C#所做的。 But what I don't want is the persistence in C#(/ASP.NET). 但是我不想要C#(/ ASP.NET)中的持久性。 I want the static property global to all instances of a class on the currently executing page only. 我只希望对当前正在执行的页面上的类的所有实例全局使用静态属性。

How can it be possible to do this? 怎么可能做到这一点?

Basically what I'm using this for is unique naming which must only be unique on the currently executing page. 基本上,我使用的是唯一名称,该名称只能在当前执行的页面上唯一。 If the static property is persistent, then there is a much higher chance of integer rollover in periods of high traffic, which could lead to the same value being used twice. 如果静态属性是持久性的,则在高流量期间发生整数翻转的可能性要高得多,这可能导致相同的值被使用两次。

Like if someone went to a page with 就像有人去

static int i=0;
page_load...{
  lbl.Text=i;
  i++;
}

then they would get 0. and if someone else went to the same page they would also get 0. But also having the static property so that it's the same in all instances of the class. 那么他们将获得0。如果其他人进入同一页面,他们也将获得0。而且还具有static属性,以便在该类的所有实例中都相同。

Unfortunately you're not going to be able to get what you want in this case because you're trying to combine two incompatible concepts 不幸的是,在这种情况下,您将无法获得想要的东西,因为您试图将两个不兼容的概念结合起来

  • static is a modifier in C# which frees a member (method, property, field, etc ...) from being bound to an instance. static是C#中的修饰符,它使成员(方法,属性,字段等)免于绑定到实例。 It's instance more accurately bound to a type within an AppDomain. 它的实例更准确地绑定到AppDomain中的类型。
  • A counter specific to the current executing page is necessarily associated with an instance 当前执行页面的特定计数器必须与实例相关联

I think your best bet is to create an instance level property and do what is needed to pass down the instance and update the counter. 我认为您最好的选择是创建一个实例级属性,并执行将实例传递给下一个实例并更新计数器所需的操作。

But I'm still a bit unclear about your scenario. 但对于您的情况,我还是不太清楚。 It seems like you could want any of the following ... 看来您可能想要以下任何一种...

  • A property specific to the currently instance of the executing page 特定于执行页面的当前实例的属性
  • A property specific to all instances of the executing page 特定于执行页面的所有实例的属性
  • A property specific to the all uses of the page within the current session 特定于当前会话中页面所有用途的属性

Could you clarify which of these is the problem? 您能说明问题中的哪一个吗?

There's no really clean way to do this, but if your object will always live in the context of a HTTP page/request, you could use the Items collection of the current HttpContext : 并没有真正干净的方法,但是如果您的对象将始终存在于HTTP页面/请求的上下文中,则可以使用当前HttpContextItems集合

public class YourClass
{
    private static readonly string _itemKey = "Key Goes Here";
    private readonly HttpContext _context;

    public YourClass()
    {
        _context = HttpContext.Current;
        if (_context == null) throw new InvalidOperationException("Boom!");

        // set a default value here if you like...
        if (_context.Items[_itemKey] == null)
        {
            _context.Items[_itemKey] = new YourType("Default Value");
        }
    }

    public YourType NonPersistentStatic
    {
        get { return (YourType)(_context.Items[_itemKey]); }
        set { _context.Items[_itemKey] = value; }
    }
}

I'm not really sure I understand your question 100% however... 我不太确定我能100%理解您的问题...

I believe what your really looking for is to store an object in the Session. 我相信您真正想要的是在Session中存储对象。

What I would do is something like this 我要做的就是这样

public class PageBase : Page
{

    public MyObject Foo 
    {
        get { return (MyObject)Session["myobject"]; }
        set { Session["myobject"] = value; }
    }
}

And change your pages to inherit from PageBase 并将您的页面更改为从PageBase继承

Edit: After looking up the implications on [ThreadStatic] inside ASP.NET I came across this blog post by Scott Hanselmen saying, no no no! 编辑:在ASP.NET中查找[ThreadStatic]的含义后,我遇到了Scott Hanselmen的这篇博客文章,说,不,不,不! A tale of two techniques: The [ThreadStatic] Attribute and System.Web.HttpContext.Current.Items . 两种技术的故事:[ThreadStatic] Attribute和System.Web.HttpContext.Current.Items He also pointed out the existence of the HttpContext having a builtin dictionary that you can store objects in. I forgot entirely about this mostly because so far I've never once found anything useful for it. 他还指出HttpContext具有内置的字典,您可以在其中存储对象。我完全忘记了这一点,主要是因为到目前为止,我从未发现有任何有用的东西。

Where are you referencing the "static" from? 您是从哪里引用“静态”的? If it is just child controls, I would add a regular instance property to your page class, then reference that variable through the page property on the child controls. 如果只是子控件,我将向您的页面类添加常规实例属性,然后通过子控件上的page属性引用该变量。

public class DefaultPage : Page {
    public string MyProperty { get; set; }
} 

public class DefaultControl : UserControl {
    //...
    ((DefaultPage)this.Page).MyProperty
    //...
}

Honestly though, if I saw this code, I would think the design is a little backwards. 但老实说,如果我看到了这段代码,我会认为设计有些倒退。 Page should be supplying the user control with all of the data it needs. Page应该为用户控件提供所需的所有数据。

What you are asking for is a ThreadStatic variable, however that is not a good solution. 您要的是ThreadStatic变量,但这不是一个好的解决方案。 It would work, but it's not a robust way to handle it. 它可以工作,但不是处理它的可靠方法。 A ThreadStatic variable is for example only initialized for the first thread, so you need to handle the initialization for each thread yourself. 例如,仅针对第一个线程初始化ThreadStatic变量,因此您需要自己处理每个线程的初始化。

First of all you should look into the built in capabilities for providing a unique id for each element. 首先,您应该研究为每个元素提供唯一ID的内置功能。 If you for example have a repeater so that the same control is repeated, each iteration gets a unique id which is prepended to the control id. 例如,如果您有一个中继器,以便重复相同的控件,则每次迭代都会获得一个唯一的ID,该ID会附加在控件ID之前。 You can use the ClientID property to get this unique id. 您可以使用ClientID属性获取此唯一ID。

If you need to handle the naming yourself, you should use a member variable in the Page class to keep track of the naming. 如果需要自己处理命名,则应在Page类中使用一个成员变量来跟踪命名。 You can easily initialize the variable in the constructor of the class, and as the variable doesn't exist before that, you are sure that you can't accidentally use it before it's initialized. 您可以轻松地在类的构造函数中初始化变量,并且由于该变量在此之前不存在,因此请确保在初始化之前不会意外使用它。

Not sure why you would need that. 不确定为什么会需要它。 You can store stuff unique to a session in the HTTPContext.Current.Session. 您可以将会话特有的内容存储在HTTPContext.Current.Session中。 You can store stuff that is unique to a request in HTTPContext.Current.ViewState. 您可以在HTTPContext.Current.ViewState中存储请求唯一的内容。

To do what you want to do, you would need to declare an application scopped variable of an object that that is threadsafe.The example below example would give you a unique number across all pages. 要执行您想做的事情,您需要为线程安全的对象声明一个应用程序作用域变量,下面的示例将为您提供所有页面的唯一编号。

1) Create a thread-safe counter class since the Application scopped variables are not thread safe by defaut 1)创建一个线程安全的计数器类,因为默认情况下Application范围变量不是线程安全的

public class ThreadSafeCounter
{
  private object _padlock = new object;
  private int _counterValue = 0;

  public int GetNextValue()
  {
     int temp;
     lock(_padlock)
     {
       _counter++;
       temp = _counter;
     }
     return temp;
  }

}

2) Create the application variable in the Global.asax Application_Start event 2)在Global.asax Application_Start事件中创建应用程序变量

HttpContext.Current.Application["MyCounter"] = new ThreadSafeCounter();

3) Access this in your page's code behind 3)在您的页面代码后面访问

var counter = HttpContext.Current.Application["MyCounter"] as ThreadSafeCounter;
if (counter != null)
{
  var uniqueValue = counter.GetNextValue();
  // DO SOME WORK HERE
}
else
{
  //throw some exception here
}

A potential gotcha: If you deploy this across a server farm or you have more than 1 worker process, make sure that your session mode is either a state server or SQL Server based because if it is InProc the each server/process that handles the request will have its own counter. 潜在的陷阱:如果在服务器场中部署该进程,或者您有多个工作进程,请确保您的会话模式是基于状态服务器或基于SQL Server的会话,因为如果是InProc,则处理请求的每个服务器/进程将有自己的柜台。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM