2012-07-21 102 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。

相关问题