簡體   English   中英

如何將方法作為另一個方法的參數傳遞

[英]How to pass method as a parameter for another method

我需要檢查在“父”對象中是否有一定的時間可以在“子”對象中調用某些方法。 例如,父對象(組件)包括子對象(或換句話說,組件),而父對象現在正在處置,因此必須禁止所有(或特定的)子活動(即,啟動新的服務線程,使新的客戶請求入隊,.. )。

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 ...
        ...            
    }
}

有什么辦法嗎?

注意:我是在回答您的問題,而不是您的標題。 其他人回答了標題。

有些對象具有isDisposed屬性,如果您的父級實現了該屬性,那是您唯一不想調用方法的屬性,那么可以。 否則沒有。 如果控制父級的源,則可以添加一個執行所需功能的屬性。

如果您不控制源代碼,並且想要檢查的不只是isDisposed,或者父項未實現isDisposed,則可以檢查公開的屬性,但通常應假定如果某個方法公開了,隨時可以調用它。 如果您通過反射調用私有方法,那么您將有機會。

編輯以回應評論:有了您的描述,代表將不會為您提供任何其他功能,您無法通過向父項添加屬性和方法來簡化工作(如果您不控制源代碼,則他們將無濟於事)所有)。 處理您所描述的場景的最佳方法(出現故障時,CAR.ENGINE.START的啟動方法是引發異常或返回表示嘗試啟動發動機的值)。

使用func Func<T, TResult> 鏈接

最簡單的方法是傳遞URI而不是引用:

例如“ NS.Child.ThirdMethod”。

否則,最接近函數引用的是委托。 您可以根據需要通過。

但是,此方法不符合OOP概念規則:基類對其子類一無所知。 最好使用某種鎖定機制來告知孩子他們無法訪問資源。

如果這些方法是子類的本地方法,那么父類肯定不會對它們有任何了解。 賴斯定理會導致您遇到各種問題,即使您看不到代碼也是如此。 如果它們是父類的本地對象,並且在子類中被覆蓋,則存在相同的問題(但程度較小),因為您不能真正保證子類會做父類的所有工作(並且僅做那些事情)上課 實際上,您幾乎可以保證它會做一些不同的事情 (如果沒有,為什么要覆蓋?)

如果它們是父類的本地對象,並且在子類中不可重寫,則只需檢查對象是否處於執行此類操作的有效狀態,否則就拋出異常。

至於實際的有效性檢查,對於您的示例,您可以使用bool IsDisposing()類的方法; 對於其他情況,您可以通過其他方式跟蹤狀態。 例如,像CanDoThisThing()這樣的私有方法可能會有所幫助。 擁有采用通用操作名稱(而不是操作;我們已經確定了該操作的不可行性)的方法在我看來有點不妥。

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

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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM