2012-05-03 4 views
4

두 클래스는 한 번만 실행 할 수 있습니다 내가 한 번만 호출하는 것이 아니라 한 번만 호출되기를 바란다. ClassA ... 현재 글로벌 속성을 설정하고있다. -Ran - 그 메소드가 이전에 실행되었는지 아닌지를 확인한다. 그것은 작동하지만 나는 이것이 최고의 디자인이 아니라고 느낍니다. 같은 일을하는 더 좋은 방법이 있는지 궁금합니다.어떻게 몇 줄의 코드가 동일한 어셈블리에서

감사합니다.

ClassA.MyMethod(...) 
{ 
.... 
//.... 
if (ClassB.Ran != 1) 
    ClassB.Foo(); 
.... 
//... 
} 
+1

아마도 가장 좋은 디자인입니다. 나는 당신이 무엇을 찾고 있는지 분명하지 않다. –

답변

9

"한 번만"제한을 얼마나 엄격하게 해석해야하는지주의해야합니다. 정적 메서드는 일반적으로 스레드로부터 안전하다고 가정합니다. , 더 이상 구체적인 내용없이

private static bool isRun = false; 
private static readonly object syncLock = new object(); 

public void MyMethod() 
{ 
    lock (syncLock) 
    { 
     if (!isRun) 
     { 
      Foo();    
      isRun = true; 
     } 
    } 
} 
+0

전화하세요. 그것을 고려할 것입니다. 감사합니다. – Bohn

+0

그건'Lazy '의 정말 멋진 기능 중 하나이기도합니다. – asawyer

+1

@asawyer : 동의하고 필드 초기화를 위해 일반적으로'Lazy '을 사용하는 것을 선호합니다. 그러나 주어진 예제는 특정 필드가 초기화되고 있음을 나타내지는 않습니다. 중요한 값을 반환하지 않고 초기화 메소드를 부작용으로 호출하는 속성 가져 오기 도구를 호출하는 것은 비 직관적입니다. – Douglas

1

작업을 수행 할 것인지 여부에 관계없이 생성자에 bool을 전달하면됩니까? 뭔가 같은 :

ClassA(bool runA) 
{ 
    if (runA) 
    { 
     ClassB.Foo(); 
    } 
} 
결과가 다시 실행을 방지, 메소드가 처음 호출을 설정됩니다 있도록이 클래스에 개인 정적 필드를 사용할 수
+0

이것은 올바른 일이 아닙니다. 호출 수신자가 호출 수신자가 함수를 실행해야하는지 여부를 알고 있다면 응답이 없을 때 전화하지 않아야합니다. '농담'이라는 메모가 첨부 된 객체에 "do something"메시지를 보내면 정말 기괴합니다. – Tim

+1

나는 그 기능이 실행되지 않았더라도 항상 'A'의 인스턴스를 원한다고 생각했다. (예제에서 제외 된 다른 클래스 멤버를 설정했을 수있다.) 어떻게 그렇게 확신 할 수 있니? – mattytommo

+0

나는 아무것도 알 수 없지만, OP가 이런 종류의 해결책을 찾고 있다는 증거가 없다면 (즉, OP는 그들이 방법이 한 번만 호출되지만 필요한 것은 아니라는 것을 보장해야한다고 말합니다.) 객체를 생성하는 동안 호출되지 않아야하며 생성 중에 호출되어야하는지 여부를 나타낼 수 있어야합니다.) 나는 그것이 존재한다고 믿을만한 이유가 없습니다. – Tim

4

:

class B 
{ 
    private static bool fooRun = false; 

    public static void Foo() 
    { 
    if (fooRun) { return; } 
    ... 
    fooRun = true; 
    } 
} 
+0

@BDotA ClassB의 코드가 실행되었는지 확인하기 위해 다른 클래스를 확인하지 않으려합니다. OOP가 좋지 않으며 코드를 유지하기 어렵습니다. 클래스 B에서 그 수표를 중앙 집중화하여, ClassB가 아담 V가 제안한 것과 같이 자신의 상태에 대한 단일 기관이되도록합니다. – EtherDragon

+0

@EtherDragon : 예, ClassB에서 아담처럼 집중시키는 것이 더 좋습니다. 감사합니다 – Bohn

7

나는 것 고려 일반적으로 Lazy<T>

이 작업을 수행 :

public static class Test // this is your ClassB 
{ 
    private static Lazy<string> m_Property = new Lazy<string>(()=> 
    { 
     Console.WriteLine("Lazy invoked"); 
     return "hi"; 
    },true); 
    public static string Property 
    { 
     get 
     { 
      Console.WriteLine("value request"); 
      return m_Property.Value; 
     } 
    } 
} 

//....consuming code, this is in your ClassA somewhere 

var test1 = Test.Property; // first call, lazy is invoked 
var test2 = Test.Property; // cached value is used, delgate not invoked 
var test3 = Test.Property; // cached value is used, delgate not invoked 
var test4 = Test.Property; // cached value is used, delgate not invoked 
var test5 = Test.Property; // cached value is used, delgate not invoked 

이 난을 출력 :

value request 
Lazy invoked 
value request 
value request 
value request 
value request 
+0

흠 ... 조금 혼란스러워? ClassA, ClassB 등과 같은 이름을 사용해 주시겠습니까? 내 머리 속에서 사용하는 habe는 내 질문에 코드를 매핑 할 수 있습니까? 덕분에 – Bohn

+0

정말 멋지다! Lazy에 관한 TIL . –

+1

@BDotA 위의 설명에 몇 가지 설명을 추가했습니다. – asawyer

1

: 당신이 정말로 당신의 방법은 심지어 경주 스레드의 경우, 한 번 실행되도록하려면, 당신은 동기화 메커니즘을 사용해야하는 가장 간단한 예는 lock 인 그것은 말하기 어렵지만 B 클래스의이 메소드는 일종의 초기화 로직을 포함하고 있습니다. B 클래스의 정적 생성자에 넣을 수있는 클래스 B를 처음 참조 할 때 뭔가 필요한 경우 클래스 A의 메서드를 참조 할 때만 B 클래스의 메서드를 실행해야하는 경우 클래스 A의 정적 생성자에서 호출됩니다. 클래스 A의 일부 메서드가 호출 될 때까지 호출 할 수없는 경우 및 어디서나 한 번만 호출해야합니다. 그런 다음 클래스 B의 개인 정적 변수를 내부에서 확인해야한다고 말합니다 메서드를 호출하고 이미 호출 된 경우 즉시 반환합니다. 그렇지 않으면, 최후의 수단으로, 클래스 A의 개인 정적 변수를 전역 변수보다 선호한다고 말하고 싶습니다.

그러나이 모든 경우에 나는 당신이 글로벌 상태를 만들고 있다고 말하고 싶습니다. 이는 거의 항상 잘못된 디자인을 나타냅니다. 겸손한 견해로, 이런 종류의 문제는 단지 "의존성 주입"에 대한 필요성을 비명을 지르고 있습니다.

관련 문제