I'm trying to find a proper way to restrict/force the usage of methods in order to ensure the correct internal handling.
Given the following abstract base class
public abstract class BaseClass
{
// needs to be overriden by concrete implementation
protected abstract void CreateInternal(object dataToCreate);
// only visible method
public void Create(object dataToCreate)
{
// check the data provided <-- this is important to be done each time
CheckData(dataToCreate);
// call implementation of concrete class
CreateInternal(dataToCreate);
}
private void CheckData(object dataToCheck)
{
if(dataToCheck == null) throw new Exception("Data is not valid");
}
}
and a simple implementation
public class ChildClass : BaseClass
{
protected override void CreateInternal(object dataToCreate)
{
// do create-stuff related to ChildClass
}
}
My question: Is there a way to restrict the access to CreateInternal
? In ChildClass
I could create a public method
public void DoStuff(object dataToDoStuff)
{
// access protected method is not forbidden
CreateInternal(dataToDoStuff);
}
This will call CreateInternal
without doing the needed checks as if it would do if called via Create
of the base-class.
Is there any way to force the usage of Create
prior to CreateInternal
? There is no need to have this at compile-time (but it would be nice), but at least at runtime.
I have something like checking who is calling in mind.
public class ChildClass : BaseClass
{
protected override void CreateInternal(object dataToCreate)
{
// if not called via base 'Create' -> throw exception
}
}
Is there some pattern I'm not aware of or is what I'm trying to achieve too weired and simply not possible?
答案 0 :(得分:2)
There is no way of really enforcing this at compile or runtime. As you well say, a virtual protected
method is reachable and overridable from any derived type so you'd always have to rely on the implementation of the overriden method making the necessary checks which kind of defeats the purpose.
IMHO your best bet is to enforce this through code reviews if you can control who's extending your class. If thats not the case then, seeing that your Create
method is not virtual and is simply changing the state of BaseClass
, why don't you call it in the constructor? Is this possible or is your example a simplified scenario and this isn't an option? Doing this would guarantee that Create
is always called first.
UPDATE: Contrary to what I said before, there are "ways" you could enforce this at runtime.
Although not shown in your example, I'm guessing there will be some kind of internal state in BaseClass
that any derived class must leverage via methods, properties, fields, etc. to be of any use (inheritance would be kind of pointless otherwise). You could always set a private flag createCalled
in BaseClass
and make all BaseClass
methods, getters (yuck) and setters check the flag and bail out with an InvalidOperationException
if its not set. This would esentially render useless any derived instance not correctly initialized. Ugly but doable.
Or even simpler, if you control all potential consumers of BaseClass
and any derived type out there in the wild, then just make the flag public public bool Initialized { get; }
and check when consuming the object and bail out if necessary.
答案 1 :(得分:0)
"Weird" would not be the word of choice of mine, but still..
As far as I can see, what you are trying to achieve is to prevent the ChildClass owner, who implemented CreateInternal()
's method body, from executing those statements without invoking CheckData()
first.
Even if this works, he can still copy and paste the statements into DoStuff()
method body and can execute them there.
We do not force, we guide.
People will follow your guideline, and they will be happy to see that their class is working according to it.