2009-09-08 4 views
1

저는 C/C++ 배경에서 왔고 C#에서 몇 가지 일을하는 데 어려움을 겪고 있습니다. 내 문제는 바로 지금 내가 C++에서 작동하는 static 키워드가 필요하다는 것입니다. 그래서 속성은 C#이하는 클래스의 모든 인스턴스에 대해 전역 적입니다. 하지만 내가 원하지 않는 것은 C# (/ ASP.NET)의 지속성입니다. 정적 속성을 전역으로 실행하려면 현재 실행중인 페이지의 클래스 인스턴스 만 필요합니다.C# 비 지속적인 '정적'키워드?

어떻게이 작업을 수행 할 수 있습니까?

기본적으로이 이름은 현재 실행중인 페이지에서만 고유해야하는 고유 한 이름 지정입니다. 정적 속성이 지속되면 트래픽이 많은 기간에 정수 롤오버가 발생할 확률이 훨씬 높아져 같은 값이 두 번 사용 될 수 있습니다.

사람이 다음

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

있는 페이지에 가면처럼 그들은 0을 얻을 것이며, 다른 사람이 같은 페이지에 가면 그들은 또한 0을 얻을 것입니다 그러나 그것은이다 그래서 또한 정적 특성을 갖는 모든 반원들에게 똑같이 적용된다.

+2

간단한 해결책은 길게 사용하는 것입니다. 64 비트 값은 언제든지 롤오버되지 않습니다. 솔직히 32 비트 정수도 의심 스럽습니다. 여전히 40 억 건이 요구됩니다.나는 당신의 위치가 평균 세션 기간 도중 많은 방문을 생성 한 ㄴ다는 것을 의심한다. – jalf

+0

아마 사실입니다. "페이지를 요청할 때마다이 숫자가 100 회 이상 증가 할 수 있다면 매우 좋은 결과가 발생할 수 있기 때문에 결코 많은 사람들이 없을 것"이라고 가정하는 것은 결코 바람직하지 않습니다. – Earlz

+1

. 페이지 당 숫자 일지라도 페이지가 자주 요청 될 경우 오버플로가 발생할 수 있습니다. 트릭은 합리적인 가정을하는 것입니다. 페이지가 얼마나 자주 요청 되든 64 비트 정수 *는 오버플로되지 않습니다 *. 나노초마다 증가시킬 수 있고, 584 년 동안 감싸지 않을 것입니다. – jalf

답변

3

이 작업을 수행 할 정말 깨끗한 방법은 없습니다 만, 개체는 항상 HTTP 페이지/요청의 맥락에서 살 것이다, 당신은 현재 HttpContextItems collection을 사용할 수 있습니다 : 당신은 무엇

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; } 
    } 
} 
+0

나는 우리 모두를 생각합니다. 이 답변 아래로 찍은있어 그리고 그것은 단지 포스터의 설정을 그는 세션 당 또는 요청 당 원하는 경우. 세션이 더 많은 이해가 왜 이후 그것은 인스턴스에 의해 처리 될 수 있기 때문에 요청에 대해서만 정적 될 것이라고 생각합니다. 전달 된 객체 또는 의존성 주입. –

0

"정적"을 어디에서 참조하고 있습니까? 그냥 자식 컨트롤 인 경우, 페이지 클래스에 일반 인스턴스 속성을 추가 한 다음 자식 컨트롤의 페이지 속성을 통해 해당 변수를 참조합니다.

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

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

정직하게도이 코드를 보면 디자인이 약간 뒤쪽이라고 생각합니다. 페이지는 필요한 모든 데이터를 사용자 정의 컨트롤에 제공해야합니다.

4

불행하게도 당신은, 당신이 호환되지 않는 두 개의 개념

  • 정적 멤버를 해제 C#에서 수정 (방법이 결합하는 것을 시도하고 있기 때문에이 경우에 당신이 원하는 것을 얻을 수있을 않을거야 속성, 필드 등)을 인스턴스에 바인딩하지 못하게합니다. 이 인스턴스는 AppDomain의 형식에보다 정확하게 바인딩됩니다.
  • 현재 실행 페이지에 특정 카운터
  • 반드시 인스턴스

와 관련된 나는 당신의 최선의 방법은 인스턴스 수준의 속성을 생성하고 인스턴스를 전달하고 카운터를 업데이트하는 데 필요한 일을하는 것입니다 생각합니다.

하지만 아직 귀하의 시나리오에 대해 조금 분명하지 않습니다. 다음 중 하나를 할 수있는 것은 실행 페이지

  • -
  • 프로퍼티 특정 실행중인 페이지의 모든 인스턴스에 특정 프로퍼티의 현재 인스턴스에 고유

    • 프로퍼티 ... 보인다 현재 세션 내에서 페이지의 모든 용도

    이 중 어떤 것이 문제인지 분명히 할 수 있습니까?

  • +0

    나는 그가이 작업을 수행 할 수 있다고 생각하지 않습니다. 특정 키워드를 사용했지만 정확한 해결책을 제공했다고 생각합니다. –

    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의 존재를 지적했습니다.이 점에 대해 전적으로 잊어 버렸습니다.

    +0

    'Session '은 (동일한 사용자에 대해) 서로 다른 요청에 걸쳐 지속됩니다. – LukeH

    +0

    @ 루케 : 그건 사실이긴하지만, 원래의 포스터가 원하는 것일 수 있습니다. – Powerlord

    +0

    아니요, 사용자별로 오버플로가 있어서는 안됩니다. (물론 누군가가 8 시간 동안 10,000 페이지 이상의 요청을 생성 할 수 없습니다 (세션이 죽어가는 것을 막기 위해 충분히 활동적이라고 가정 할 때) – Earlz

    0

    ThreadStatic 변수가 필요하지만 좋은 해결책은 아닙니다. 그것은 효과가 있지만, 그것을 다루는 견고한 방법은 아닙니다. ThreadStatic 변수는 예를 들어 첫 번째 스레드에 대해서만 초기화되므로 각 스레드에 대한 초기화를 직접 처리해야합니다.

    먼저 각 요소에 대해 고유 ID를 제공하는 기능을 살펴보아야합니다. 예를 들어 같은 컨트롤이 반복되도록 리피터가있는 경우 각 반복은 컨트롤 ID 앞에 추가되는 고유 한 ID를 얻습니다. ClientID 속성을 사용하여이 고유 ID를 가져올 수 있습니다.

    직접 이름을 처리해야하는 경우 Page 클래스의 멤버 변수를 사용하여 이름을 추적해야합니다. 클래스의 생성자에서 변수를 쉽게 초기화 할 수 있으며 그 전에 변수가 존재하지 않으므로 초기화되기 전에 실수로 사용할 수 없다는 것을 확신 할 수 있습니다.

    0

    필요한 이유가 확실하지 않습니다. HTTPContext.Current.Session에 세션에 고유 한 항목을 저장할 수 있습니다. HTTPContext.Current.ViewState에서 요청에 고유 한 항목을 저장할 수 있습니다.

    원하는 작업을 수행하려면 스레드 세이프 인 객체의 응용 프로그램 캡처 변수를 선언해야합니다. 아래 예는 모든 페이지에서 고유 번호를 제공합니다.

    1) 어플리케이션 변수

    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 이벤트 프로그램 변수를 생성 defaut에 의해 스레드 안전하지 scopped 때문에 스레드 안전성 카운터 클래스를 생성

    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 
    } 
    

    발생 가능한 문제 : 서버 팜에 배포하거나 2 개 이상의 작업자 프로세스가있는 경우 세션 모드가 상태 서버 또는 SQL Server 기반인지 확인합니다. 이는 InProc 인 경우 각 서버/프로세스가 요청을 처리하면 자체 카운터가 있습니다.