我需要检查父母"对象在某个特定的时刻可以接受在" child"中调用某些方法。例如,父对象(组件)包括子对象(或者换句话说是组件),而父对象现在正在处理,因此必须禁止所有(或特定的)子活动(即启动新的服务线程,将新的客户端请求排入队列,... )。
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 :(得分:7)
注意:我正在回答你的问题,而不是你的头衔。其他人已经回答了这个标题。
某些对象具有isDisposed属性,如果您的父实现了该属性,并且这是您不想调用方法的唯一时间,那么是。否则没有。如果您控制父项的源,您可以添加一个符合您需要的属性。
如果您不控制源并且想要检查多于isDisposed或者父级没有实现isDisposed,您可能能够检查公开的属性,但通常您应该假设如果方法暴露于公众,任何时候都可以接听。如果你通过反思调用私人方法,那么你就是冒险。
编辑以回复评论: 根据您的描述,代表不会通过向父级添加属性和方法来为您提供任何额外的功能(如果您不控制源,它们根本不会帮助)。处理您描述的场景的最佳方法(CAR.ENGINE.START失去气体时,Start方法要么抛出异常,要么返回值指示尝试启动引擎的结果)。
答案 1 :(得分:2)
答案 2 :(得分:0)
使用func Func<T, TResult>
link
答案 3 :(得分:0)
最简单的方法是传递URI而不是引用:
“NS.Child.ThirdMethod”例如。
否则,委托是最接近函数引用的。如果你愿意,你可以传递它。
但是,此方法不符合OOP概念规则:基类应该对其子类没有任何了解。 最好使用某种锁定机制告诉孩子他们无法访问资源。
答案 4 :(得分:0)
如果这些方法是子类的原生方法,则父级无法确切了解它们。如果你甚至可以看到代码,那么Rice's Theorem会给你带来各种各样的问题。同样的问题(但程度较小),如果它们是父类的原生并且正在孩子中被覆盖,因为你不能真正保证子类将完成所有(并且只有那些事情)父类上课;事实上,你可以保证它会做某种不同的事情。 (如果没有,为什么要覆盖?)
如果它们是父类的原生且在子类中不可覆盖,那么只需检查对象是否处于有效状态以执行此类操作,如果不是则抛出异常。
就实际有效性检查而言,对于您的示例,您可以使用bool IsDisposing()
之类的方法;对于其他情况,您可能会以其他方式跟踪状态。例如,像CanDoThisThing()
这样的私有方法可能有所帮助。有一个采用通用操作名称的方法(不是一个操作;我们已经确定了它的不可行性)对我来说似乎有些不妥。
答案 5 :(得分: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。