2012-07-21 110 views
0

我需要在「父」對象中檢查是否存在可以在某個時刻調用某個方法的「子」。例如,父對象(組件)包含子對象(換句話說就是組件部分),父對象現在處置,因此必須禁止所有(或特定)子活動(即啓動新的服務線程,排隊新的客戶端請求,.. )。如何將方法作爲參數傳遞給另一個方法

public class Parent 
{ 
    public bool IsMethodCallAcceptable(reference_to_method) {...} 
} 

public class Child 
{ 
    public int SomeMethod(int intArg, string stringArg) 
    { 
     if(!_parent.IsMethodCallAcceptable(reference_to_SomeMethod_with_actual_args)) 
      throw new ... 
     ... 
    } 

    private void AnotherMethod(string param = null) {...} 
    { 
     if(!_parent.IsMethodCallAcceptable(reference_to_AnotherMethod_with_actual_args)) 
      throw new ... 
     ... 
    } 

    private Guid ThirdMethod() 
    { 
     if(!_parent.IsMethodCallAcceptable(reference_to_ThirdMethod)) 
      throw new ... 
     ...    
    } 
} 

有沒有辦法做到這一點?

+0

感謝所有值得尊敬的對話參與者。可能是由於缺乏英語經驗,我以不正確的方式使用了一些術語。 – JSP 2012-07-21 18:48:40

+0

該主題不是父類在子類(OOP範式)中的關係,而是組件的單獨部分和通用組件代碼之間的關係。例如,我們有一個組件CAR,它由四個WHEEL,一個ENGINE等組成。我們可以調用CAR.ENGINE.START,但是如果CAR.FUEL_TANK.GASOLINE_VOLUME = 0,我們的CAR不能移動,所以它的引擎啓動不正確。所以我需要檢查組件的部件方法調用,並且我的CAR對這些方法足夠了解。 – JSP 2012-07-21 18:57:53

+0

現在使用的代表看起來最接受,謝謝你,海德里安。但是我需要寫很多代表,同時想寫一個通用的檢查方法。 – JSP 2012-07-21 18:59:50

回答

2
+0

不錯的答案雖然有點短 – jclozano 2012-07-21 18:05:41

+1

@jclozano - 是的,我想幫助更多,但我沒有如此經驗。希望有人能夠幫助更好,但至少這會讓他/她指向正確的方向。 – Haedrian 2012-07-21 18:12:34

+0

代表可以用作*調用特定方法的方式*;但是,父母如何告訴*哪個* Child方法是委託的目標?這些信息甚至是代表的一部分(由方法組創建)? – 2012-07-21 18:45:18

0

使用FUNC Func<T, TResult> link

0

最簡單的方法是通過一個URI代替參考的:

「NS.Child.ThirdMethod」 例如。

否則,委託是最接近函數引用的東西。如果你願意,你可以通過。

但是,這種方法不符合OOP概念規則:基類應該對它的子類不知道。 最好使用某種鎖定機制來告訴孩子他們不能訪問資源。

7

注:我回答你的問題,而不是你的標題。其他人已經回答了標題。

某些對象具有isDisposed屬性,如果您的父母實現了這一點,那是唯一一次您不想調用方法,那麼是的。否則不。如果您控制父級的源代碼,則可以添加一個屬性來執行所需操作。

如果您不控制源,並且想要檢查isDisposed以上或父類未實現isDisposed,那麼您可能能夠檢查公開公開的屬性,但通常應該假設如果某個方法已暴露對公衆而言,任何時候都可以接受。如果你通過反射來調用私有方法,那麼你正在冒險。響應

編輯評論: 鑑於你的描述,代表們將不會給你任何額外的功能,你無法通過增加屬性和方法到父(如果你不控制源頭做更容易,他們根本沒有幫助)。處理你描述的場景的最佳方法(CAR.ENGINE.START在氣體不足時,是用Start方法拋出異常或返回一個表示啓動引擎的嘗試結果的值)。

0

如果這些方法是子類的本地方法,那麼父類肯定無法知道它們的任何內容。 Rice's Theorem會導致你所有的問題,如果你甚至可以看到代碼。同樣的問題(但程度較輕),如果它們是父類的本地類,並且在子類中被覆蓋,因爲你無法真正保證子類會做所有的事情(只有那些東西)班級確實;其實你們都可以保證會做東西不同。 (如果沒有,爲什麼要重寫?)

如果它們是父類的本地類,並且不能在子類中重載,那麼只需檢查該對象是否處於有效狀態以便執行此類操作並拋出如果不是,則爲異常。

就實際有效性檢查而言,對於您的示例,您可以使用如bool IsDisposing();對於其他情況,您可能會以其他方式跟蹤狀態。例如,像CanDoThisThing()這樣的私有方法可能會有所幫助。有一個方法需要一個通用的操作名稱(不是操作;我們已經確定了這個操作的不可行性)似乎有點讓我失望。

+0

代碼沒有顯示任何繼承,但是如果孩子是從父代派生的,那麼它可能知道它正在被處置。 – jmoreno 2012-07-21 18:54:01

+0

@jmoreno:它可以,但它不知道「這個方法是否合適」(使用變量方法和參數以及所有內容)而不知道父母的狀態並自行做出決定。關於所有它可能知道的事情,沒有徹底破壞封裝,就是它是否被處置 - 甚至暴露出很多可能和破碎的氣味給我。 (如果你的物體被丟棄......爲什麼在53462地獄裏你仍然有它,更不用說使用它了?如果它的構建方式可以...爲什麼它是一次性的?) – cHao 2012-07-21 19:03:04

0

謝謝大家再次,結果在第一種方法如下

public class Component 
{ 
    public ComponentPart SomeComponentPart1 { get; private set; } 
    public ComponentPart SomeComponentPart2 { get; private set; } 

    public Component() 
    { 
     SomeComponentPart1 = new ComponentPart(this); 
     SomeComponentPart2 = new ComponentPart(this); 
    } 

    public bool IsMethodCallAcceptable(MethodCallExpression method, object[] parameters) 
    { 
     // collect needed information about caller 
     var caller = (method.Object as ConstantExpression).Value; 
     var methodName = method.Method.Name; 
     var paramsArray = new Dictionary<string, object>(); 

     for (int i = 0; i < method.Arguments.Count; i++) 
      paramsArray.Add((method.Arguments[i] as MemberExpression).Member.Name, parameters[i]); 

     // make corresponding decisions 
     if (caller == SomeComponentPart2) 
      if (methodName == "SomeMethod") 
       if ((int) paramsArray["intArg"] == 0 || (string) paramsArray["stringArg"] == "") 
        return false; 

     return true; 
    } 
} 

public class ComponentPart 
{ 
    private Component Owner { get; set; } 

    public ComponentPart(Component owner) 
    { 
     Owner = owner; 
    } 

    public int SomeMethod(int intArg, string stringArg) 
    { 
     // check if the method call with provided parameters is acceptable 
     Expression<Func<int, string, int>> expr = (i, s) => SomeMethod(intArg, stringArg); 
     if (!Owner.IsMethodCallAcceptable(expr.Body as MethodCallExpression, new object[] { intArg, stringArg })) 
      throw new Exception(); 

     // do some work 
     return stringArg.Length + intArg; 
    } 

    public void AnotherMethod(bool boolArg, Dictionary<Guid, DateTime> crazyArg, string stringArg, object objectArg) 
    { 
     // check if the method call with provided parameters is acceptable 
     Expression<Action<bool, Dictionary<Guid, DateTime>, string, object>> expr = 
      (b, times, arg3, arg4) => AnotherMethod(boolArg, crazyArg, stringArg, objectArg); 
     if (!Owner.IsMethodCallAcceptable(expr.Body as MethodCallExpression, new [] { boolArg, crazyArg, stringArg, objectArg })) 
      throw new Exception(); 

     // do some work 
     var g = new Guid(); 
     var d = DateTime.UtcNow; 
    } 
} 

這是變異如何檢查方法調用上市,同樣的方法也以檢查屬性中使用的值的變化,而一些ComponentPart的方法和屬性可以檢查一些公共的Component.State屬性(通過ComponentPart.Owner)而不是調用Component.IsMethodCallAcceptable或Component.IsPropertyChangeAcceptable。

相關問題