[英]encapsulation and friendship in C#
I have a particular case in my current project.我目前的项目中有一个特殊案例。
I have:我有:
public class A
{
// etc.
}
public class B
{
// etc.
private void HandleSomeEvent(object parameter)
{
// Etc.
}
protected void HandleSomeOtherEvent(object parameter)
{
// Etc.
}
}
I want:我想:
A
to be able to call the private method B.HandleSomeEvent
, but no other class (but B
) to be able to do that A
能够调用私有方法B.HandleSomeEvent
,但没有其他 class (但B
)能够做到这一点A
to be able to call the protected method B.HandleSomeOtherEvent
, but no other class (but B
and B
's derived classes) to be able to do that A
能够调用受保护的方法B.HandleSomeOtherEvent
,但没有其他 class (但B
和B
的派生类)能够做到这一点Is that possible in C#?在 C# 中可能吗?
B
as much as possible from tampering from, say, a class C
in the same assembly?B
免受同一组件中的 class C
的篡改?It is possible by emitting an interface of A then separating it from a concrete implementation.可以通过发出 A 的接口然后将其与具体实现分离。 Once you did it you can write something like this
一旦你做到了,你可以写这样的东西
interface IA { }
class A : IA
{
public static IA New() { return new A(); }
private A() { }
private void UseB()
{
var b = new B();
b.HandleSomeEvent(this, null);
}
}
class B
{
public void HandleSomeEvent(A onlyAccess, object parameter) { }
}
In spite of the fact that HandleSomeEvent()
is public only A can access it, since no one else can possibly get a concrete instance of A class.尽管
HandleSomeEvent()
是公共的,但只有 A 可以访问它,因为没有其他人可以得到 A class 的具体实例。 It has a private constructor, while the factory New()
method returns an interface.它有一个私有构造函数,而工厂
New()
方法返回一个接口。
See my article Friends and internal interface members at no cost with coding to interfaces for details.有关详细信息,请参阅我的文章Friends and internal interface members at no cost with coding to interfaces 。
Is that possible in C#?
在 C# 中可能吗?
No, unless you use reflection: private and protected members are not accessible from other classes.不,除非您使用反射:其他类无法访问私有成员和受保护成员。
If not possible, what are the alternatives which can protect B as much as possible from tampering from, say, a class C in the same assembly?
如果不可能,有哪些替代方案可以尽可能保护 B 免受同一组件中的 class C 的篡改?
You could make B a nested class inside A and make it private.您可以将 B 设为 A 内的嵌套 class 并将其设为私有。 Then you can safely increase the visibility of the two methods of B as only A will be able to call them (unless reflection is used).
然后您可以安全地增加 B 的两种方法的可见性,因为只有 A 能够调用它们(除非使用反射)。
It is possible, but I'd usually just go with internal
and assume that other classes in the assembly are well behaved.这是可能的,但我通常只使用带
internal
的 go 并假设程序集中的其他类表现良好。
You could for example pass delegates to these methods to class A which stores them in protected static
fields/properties.例如,您可以将这些方法的委托传递给 class A,后者将它们存储在
protected static
字段/属性中。
"2. If not possible, what are the alternatives which can protect B as much as possible from tampering from, say, a class C in the same assembly?" “2. 如果不可能,有哪些替代方案可以尽可能保护 B 免受同一组件中的 class C 的篡改?”
Would checking the type info of the caller and throwing an exception work?检查调用者的类型信息并抛出异常是否有效?
[MethodImpl(MethodImplOptions.NoInlining)]
private void HandleSomeEvent(object parameter)
{
StackTrace stackTrace = new StackTrace();
StackFrame stackFrame = stackTrace.GetFrame(1);
MethodBase methodBase = stackFrame.GetMethod();
if(methodBase.DeclaringType == typeof(ClassA)) // Okay.
else if (methodBase.DeclaringType == typeof(ClassB)) // Okay.
else throw new ApplicationException("Not Okay");
}
As your class A
should be able to call protected
methods on B
, I figure it has some sort of relationship with it.由于您的 class
A
应该能够在B
上调用protected
的方法,我认为它与它有某种关系。 Ask yourself if there is a "is-a" relationship, as in "A is a B".问问自己是否存在“is-a”关系,例如“A is a B”。 In this case, you can make
A
inherit from B
:在这种情况下,您可以让
A
从B
继承:
public class A : B
{
}
Now, you are able to call protected methods on B
.现在,您可以在
B
上调用受保护的方法。 But please, don't just inherit, always ask yourself if the inheritance makes sense.但是请不要仅仅继承,要经常问自己 inheritance 是否有意义。
You can mark both methods as internal
:您可以将这两种方法标记为
internal
:
internal void HandleSomeEvent(object parameter)
{
// Etc.
}
protected internal void HandleSomeOtherEvent(object parameter)
{
// Etc.
}
This makes the two methods visible to all classes in the same assembly (and also the second method visible to all classes derived from B
).这使得这两种方法对同一程序集中的所有类都可见(并且第二种方法对从
B
派生的所有类都可见)。
There is no way to make a method visible to a specific other class.无法使方法对特定的其他 class 可见。 After all, you're the one who's controlling all classes in your assembly, so it's up to you to make sure that no other class than
A
calls the methods.毕竟,您是控制程序集中所有类的人,因此您需要确保除
A
之外没有其他 class 调用这些方法。
If you really need help from a tool with this, you could write an FxCop rule or create some kind of post-built action that checks for method calls from other classes than A
.如果你真的需要这个工具的帮助,你可以编写一个 FxCop 规则或创建某种后期构建操作来检查来自
A
以外的其他类的方法调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.