C# 如何将方法作为另一个方法的参数传递

C# 如何将方法作为另一个方法的参数传递,c#,C#,我需要检查在“parent”对象中是否有一个可接受的方法在某个特定时刻调用“child”中的某个方法。例如,父对象(组件)包括子对象(换句话说就是组件部分),而父对象现在正在处理,因此必须禁止所有(或特定)子活动(即启动新服务线程、将新客户端请求排队等) 有什么办法吗?使用代理 使用funcfunc 最简单的方法是传递URI而不是引用: 例如“NS.Child.ThirdMethod” 否则,委托就是最接近函数引用的对象。如果你愿意,你可以通过 然而,此方法不符合OOP概念规则:基类应该对其子类

我需要检查在“parent”对象中是否有一个可接受的方法在某个特定时刻调用“child”中的某个方法。例如,父对象(组件)包括子对象(换句话说就是组件部分),而父对象现在正在处理,因此必须禁止所有(或特定)子活动(即启动新服务线程、将新客户端请求排队等)

有什么办法吗?

使用代理

使用func
func

最简单的方法是传递URI而不是引用:

例如“NS.Child.ThirdMethod”

否则,委托就是最接近函数引用的对象。如果你愿意,你可以通过

然而,此方法不符合OOP概念规则:基类应该对其子类一无所知。
最好使用某种锁定机制告诉孩子们他们无法访问资源。

注意:我回答的是你的问题,而不是你的标题。其他人回答了这个问题

有些对象具有isDisposed属性,如果您的父对象实现了该属性,并且这是您唯一不想调用方法的时候,那么是的。否则不会。如果您控制父对象的源,则可以添加符合您需要的属性

如果您不控制源代码,并且希望检查的内容超过isDisposed,或者父级未实现isDisposed,则可以检查公开的属性,但通常您应该假设如果某个方法公开,则可以随时调用它。如果您通过反射调用私有方法,那么您就是在冒险

编辑以回应评论:
根据您的描述,委托不会为您提供任何通过向父级添加属性和方法无法轻松实现的附加功能(如果您不控制源代码,它们将毫无帮助)。处理您描述的场景(汽油用完时CAR.ENGINE.START)的最佳方法是让START方法抛出异常或返回指示尝试启动引擎结果的值。

如果这些方法是子类固有的,则父类无法确切了解它们。如果你能看到代码,会给你带来各种各样的问题。如果它们是父类固有的,并且在子类中被重写,则会出现相同的问题(但程度较轻),因为您不能真正保证子类将完成父类所做的所有事情(并且只完成那些事情);事实上,你几乎可以保证它会做一些不同的事情。(如果没有,为什么要覆盖?)

如果它们是父类固有的,并且在子类中不可重写,那么只需检查对象是否处于执行此类操作的有效状态,如果不是,则抛出异常


至于实际有效性检查,例如,您可以使用类似于
bool IsDisposing()
的方法;对于其他情况,您可以通过其他方式跟踪状态。例如,像
candothisting()
这样的私有方法可能会有所帮助。拥有一个采用通用操作名的方法(不是一个操作;我们已经确定了它的不可行性)对我来说似乎有点破绽。

再次感谢大家,第一种方法的结果如下所示

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;
    }
}
公共类组件
{
public ComponentPart SomeComponentPart1{get;private set;}
public ComponentPart SomeComponentPart2{get;private set;}
公共部分()
{
SomeComponentPart1=新的ComponentPart(本);
SomeComponentPart2=新的ComponentPart(本);
}
public bool IsMethodCallAcceptable(MethodCallExpression方法,对象[]参数)
{
//收集所需的来电者信息
var调用者=(作为ConstantExpression的method.Object).Value;
var methodName=method.method.Name;
var paramsArray=新字典();
for(int i=0;isomethod(intArg,stringArg);
if(!Owner.IsMethodCallAcceptable(expr.Body作为MethodCallExpression,新对象[]{intArg,stringArg}))
抛出新异常();
//做些工作
返回stringArg.Length+intArg;
}
public-void-AnotherMethod(bool-boolArg、Dictionary-frazzyarg、string-stringArg、object-objectArg)
{
//检查提供参数的方法调用是否可接受
表达式表达式=
(b,times,arg3,arg4)=>AnotherMethod(boolArg,crazyArg,stringArg,objectArg);
if(!Owner.IsMethodCallAcceptable(expr.Body作为MethodCallExpression,new[]{boolArg,crazyArg,stringArg,objectArg}))
抛出新异常();
//做些工作
var g=新Guid();
var d=DateTime.UtcNow;
}
}

这是检查方法调用的变体,可以使用相同的方法检查属性值的更改,而某些ComponentPart的方法和属性可以检查某些公共Component.State属性(通过ComponentPart.Owner)而不是调用Component.IsMethodCallAcceptable或Component.IsPropertyChangeAcceptable。

回答不错,虽然有一点short@jclozano-Y
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;
    }
}