我来自C / C ++背景,在使用C#做一些事情时遇到了麻烦。我现在的问题是我需要一个像C ++一样的static
关键字。因此,该属性对于类的所有实例都是全局的,这就是C#所做的。但我不想要的是C#(/ ASP.NET)中的持久性。我希望static属性global只对当前正在执行的页面上的所有类实例。
怎么可能这样做?
基本上我正在使用它的是唯一命名,它必须在当前正在执行的页面上是唯一的。如果静态属性是持久的,那么在高流量时段中整数翻转的可能性要高得多,这可能导致相同的值被使用两次。
就像有人带着
去了一个页面static int i=0;
page_load...{
lbl.Text=i;
i++;
}
然后他们会得到0.如果其他人去了同一个页面,他们也会得到0.但是也有静态属性,所以在类的所有实例中它都是相同的。
答案 0 :(得分:4)
不幸的是,在这种情况下,你无法获得你想要的东西,因为你试图结合两个不兼容的概念
我认为最好的办法是创建一个实例级属性,然后执行传递实例并更新计数器所需的内容。
但我对你的情况仍然有点不清楚。看起来你可能想要以下任何一个......
你能澄清一下这是哪个问题吗?
答案 1 :(得分:3)
没有真正干净的方法,但如果您的对象始终存在于HTTP页面/请求的上下文中,您可以使用当前HttpContext
的{{3}}:
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; }
}
}
答案 2 :(得分:1)
我不确定我100%理解你的问题但是......
我相信你真正想要的是在会话中存储一个对象。
我会做的是这样的事情
public class PageBase : Page
{
public MyObject Foo
{
get { return (MyObject)Session["myobject"]; }
set { Session["myobject"] = value; }
}
}
将页面更改为继承自PageBase
编辑:在查看ASP.NET内部对[ThreadStatic]
的影响后,我发现Scott Hanselmen撰写的这篇博文中,不,不,不! A tale of two techniques: The [ThreadStatic] Attribute and System.Web.HttpContext.Current.Items。他还指出了HttpContext的存在,它有一个你可以存储对象的内置字典。我完全忘记了这一点,因为到目前为止我从来没有发现任何有用的东西。
答案 3 :(得分:0)
你在哪里引用“静态”?如果它只是子控件,我会在页面类中添加一个常规实例属性,然后通过子控件上的page属性引用该变量。
public class DefaultPage : Page {
public string MyProperty { get; set; }
}
public class DefaultControl : UserControl {
//...
((DefaultPage)this.Page).MyProperty
//...
}
老实说,如果我看到这段代码,我认为设计有点倒退。页面应该为用户控件提供所需的所有数据。
答案 4 :(得分:0)
您要求的是ThreadStatic变量,但这不是一个好的解决方案。它会工作,但它不是一个强有力的方法来处理它。例如,ThreadStatic变量仅为第一个线程初始化,因此您需要自己处理每个线程的初始化。
首先,您应该研究内置功能,为每个元素提供唯一的ID。例如,如果你有一个转发器,以便重复相同的控制,每次迭代都会得到一个唯一的id,它被添加到控件id之前。您可以使用ClientID属性来获取此唯一ID。
如果您需要自己处理命名,则应使用Page类中的成员变量来跟踪命名。您可以在类的构造函数中轻松初始化变量,并且由于变量在此之前不存在,您确信在初始化之前不会意外地使用它。
答案 5 :(得分:0)
不确定为什么你需要那个。您可以在HTTPContext.Current.Session中存储会话特有的内容。您可以在HTTPContext.Current.ViewState中存储请求唯一的内容。
要执行您想要执行的操作,您需要声明一个对象的应用程序scopped变量,该变量是线程安全的。下面的示例示例将为您提供所有页面的唯一编号。
1)创建一个线程安全的计数器类,因为应用程序scopped变量不是defaut的线程安全
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)在Global.asax Application_Start事件中创建应用程序变量
HttpContext.Current.Application["MyCounter"] = new ThreadSafeCounter();
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
}
潜在的问题: 如果您在服务器场中部署它或者您有多个工作进程,请确保您的会话模式是状态服务器或基于SQL Server,因为如果它是InProc,则处理请求的每个服务器/进程将拥有自己的计数器。