Pattern for allowing client delegate to override default behavior - c#

I have a C# class that has some functionality that I'd like to allow a client of the class to override. Specifically I'd like the following:
If the client does nothing, they get our default behavior
The client can override the behavior and cause our default behavior to not be called.
The client can override the behavior and cause our default behavior to be called as a pre/post/middle operation.
My current thinking is to:
Expose an event that the client would subscribe to if they wanted to override the behavior.
Expose a method with the default behavior (that matches the signature of the event):
void DefaultBehavior()
Whenever we attempt to fire the event, if the delegate is null, we call our default behavior method, otherwise, we call the delegate of the event:
if (eventDelegate == null)
DefaultBehavior();
else
eventDelegate();
When the client overrides the behavior they can optionally call our DefaultBehavior method to get the desired behavior.
Do you think this approach will be intuitive enough from the client's perspective? Or can you suggest any alternatives that might be better?

Well, if you want your client to override some behavior, why not create a virtual function, an let the client actually override it?
It's the straightforward way of accomplishing this. No need to reinvent the wheel.

If I understand your question, by client you mean some code calling your class, and not overriding your class, assuming you need to do it this way (I agree with #zmbq answer if you can do it that way):
You can make your method have 2 overloads, one with no parameters and another receiving a Action object
public void methodName()
public void methodName(Action delegate)
then in the body of methodName() you will call the other method with defaultAction
public void methodName()
{
methodName(DefaultBehavior);
}
finally in the second method you just call the delegate passed as parameter, without caring if it's the default or not
public void methodName(Action delegate)
{
delegate();
}
the client of your class will see this two overloads and decide wether to use the default or give a custom behavior
EDIT:
Ok, last try :), according to your last comment would it work for you to have an instance field
private Action behaviorDelegate = DefaultBehavior;
Anywhere in your class you can assign to behaviorDelegate a different behavior, and then you don't need an if statement since the behavior will always be in delegate variable whether it is the default or not. It is not a big change but it seems cleaner to me.

You could (perhaps?) also do it without events:
Declaration:
public class DemoClass
{
public delegate string MyDelegate(string testValue);
public static MyDelegate DefaultBehavior
{
get
{
return testValue =>
{
return String.Concat(testValue,
", now with 99% more exclamation points!!!!!!!!");
};
}
}
public MyDelegate ModifyString = testValue =>
{
return DemoClass.DefaultBehavior(testValue);
};
}
Use:
// first, default:
DemoClass demoObject = new DemoClass();
Console.WriteLine(demoObject.ModifyString("My test string"));
// now, pure "override":
demoObject.ModifyString = testVal =>
{ return String.Concat(testVal, ", this time with question marks????");
};
Console.WriteLine(demoObject.ModifyString("Second test string"));
// finally, define a delegate that overrides and calls default:
DemoClass.MyDelegate combined = testVal =>
{ return String.Concat(DemoClass.DefaultBehavior(testVal),
", now we're really tricky");
};
demoObject.ModifyString = combined;
Console.WriteLine(demoObject.ModifyString("Third test string"));
Output:
My test string, now with 99% more exclamation points!!!!!!!!
Second test string, this time with question marks????
Third test string, now with 99% more exclamation points!!!!!!!!, now we're really tricky

Just use a virtual method:
public class BaseClass {
public virtual void Something() {
Console.WriteLine("base functionality");
}
}
public class Sub1 : BaseClass {
public override void Something() {
// do whatever you want here
base.Something(); // don't call it at all if you like
// do whatever you want here
}
}

Related

NSubstitute ForPartsOf calling concrete implementation event when substituted

I have the following class:
public class MyClass : IMyClass
{
public string MyFunc(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new Exception("Blank Name");
}
return name;
}
public double MyFuncWrapper(string name)
{
var value = MyFunc(name);
return value;
}
In trying to test it, I was under the impression that NSubstitute's ForPartsOf effectively subclassed my class and replaced the flagged methods; so I did this:
[Fact]
public void TestMyFuncWrapper()
{
// Arrange
var myClass = Substitute.ForPartsOf<MyClass>();
myClass.MyFunc(Arg.Any<string>()).Returns("Test");
// Act
var result = myClass.MyFuncWrapper("");
// Assert
Assert.Equal("Test", result);
}
However, I get the exception raised from, what I understood to be, my substituted method. Oddly, it appears that the following line:
myClass.MyFunc(Arg.Any<string>()).Returns("Test");
Is actually calling the concrete function immediately. Looking here, it appeared that a construct like this may solve the problem (although it does use the phrase "playing it safe" which sounds quite vague):
myClass.When(a => a.MyFunc(Arg.Any<string>())).DoNotCallBase();
However, calling this actually invokes MyFunc immediately in the same way. Clearly I'd misunderstood the ForPartsOf method; my question is: can I do what I'm attempting using NSubstitute, or do I need to resort to manually subclassing MyClass?
This is by design for NSubstitute (and for most mocking frameworks).
The docs state:
For starters, NSubstitute can only work with virtual members of the
class, so any non-virtual code in the class will actually execute!
Thus, you need to add virtual to the function declarations you plan to mock.
Or (as per the docs):
If possible, stick to substituting interfaces.

Delegate example what's the point

Like many other posts I've found on SO, I'm trying to get my head around delegates. Hopefully this example is not classed a duplicate because I am asking a specific question about a particular example.
public delegate void HelloFunctionDelegate(string message);
public class Delegate
{
static void Main()
{
HelloFunctionDelegate del = new HelloFunctionDelegate(GoodNight); // delegate will point to the GoodNight method
del("Hello"); // invoke the delegate
}
public static void GoodMorning(string strMessage)
{
Console.WriteLine(strMessage + " and good morning!");
Console.ReadKey();
}
public static void GoodNight(string strMessage)
{
Console.WriteLine(strMessage + " and good night!");
Console.ReadKey();
}
}
So in my example I understand that my delegate is a reference to any function that matches its signature and if I pass in GoodMorning I will see:
Hello and good morning!
and if I pass in GoodNight I will see: Hello and good night!
So its kind of like going through a middle man...
I don't understand is what's the point, why wouldn't I just directly call my GoodMorning / GoodNight methods as and when I need to use them?
Maybe there are better examples for when a delegate is useful, but in this example, why don't I just bypass the middle man?
Since you are asking concretely about this example and not in general: There is no point to doing that in this particular piece of code. It teaches you the mechanics of delegates but it does not teach you the point of using them.
In short, the point is that some piece of code can take a reference to a method without knowing what method it will actually receive. It can later call that delegate at will. That enables more abstractions than otherwise possible.
Consider you have the following delegate:
public delegate void CarEvent(Car car);
And then you have an implementation like the following:
public class Car : DataRecord
{
// An event to execute when the record is deleted
public CarEvent OnDelete { get; set; }
public void Delete()
{
this.DeleteRecord(); // Deletes this record from ex. the database
if (OnDelete)
{
OnDelete(this); // Executes the event
}
}
}
By using a delegate you can subscribe different methods to the OnDelete allowing you to do different things when the record is deleted.
Ex. you can make it so when the record is deleted it's deleted from a "ListView" that holds it.
public class CarList : ListView
{
public CarList()
: base()
{
foreach (var car in CarRecords.LoadCars())
{
var listViewItem = new ListViewItem(car);
car.OnDelete = this.DeleteCarFromList;
this.Items.Add(listViewItem);
}
}
private void DeleteCarFromList(Car deletedCar)
{
this.Items.Remove(deletedCar);
}
}
Of course the above is a rough example and there is a lot more things and different kind of situations where you can use delegates and most notably if you want to use them for events you should consider implementing them using the event keyword. - https://msdn.microsoft.com/en-us/library/awbftdfh.aspx
All in all you want to use delegates when the behavior may differ depending on the overall implementation of something. Like you might want to do one thing in one situation and something else in another situation, but they should both over-all do the same thing.
If you do not need different behaviors based on implementation then there's no need to use delegates. You'd always want to call a method directly if possible.
I hope this explained it okay.

Why are these two methods not ambiguous?

This is the signature for the Ok() method in ApiController:
protected internal virtual OkResult Ok();
And this is my method from my RestController class (which extends from ApiController):
// Note that I'm not overriding base method
protected IHttpActionResult Ok(string message = null);
Since OkResult implements IHttpActionResult, both of these methods can be called like this:
IHttpActionResult result = Ok();
In fact, that's what I'm doing in my application.
My class PersistenceRestController (which extends from RestController), has these lines of code:
protected override async Task<IHttpActionResult> Delete(Key id)
{
bool deleted = //... Attempts to delete entity
if(deleted) return Ok();
else return NotFound();
}
This compiles fine, and no warning is raised about method ambiguity. Why is that?
PersistenceRestController has also inherited the protected methods from ApiController so it should have both versions of Ok() (and it does).
At execution, the method executed is the one from my RestController.
How does the compiler know which method to run?
Jon Skeet answered a similar question (without the inheritance complication) here:
When the compiler has two otherwise-equal options to choose from, it will use an overload which doesn't need use any unsupplied optional parameters in preference to one that does...
In your case, however, the method from the RestController is being chosen because it's the more derived class. Jon does a good job of addressing the topic in detail in his book C# in Depth -- look at the inheritance section of that page, which essentially states that the compiler will prefer a method on the actual instance class before methods on less derived classes.
EDIT:
I am leaving my original answer for posterity because I think it lets you visualize things, but DO NOT BE CONFUSED! The compiler does not actually treat the optional parameter as syntactic sugar for an overridden method. It treats it as a single method with an optional parameter. Dusty's answer, mentioning that "the method from the RestController is being chosen because it's the more derived class," is correct.
ORIGINAL (With visible edits for correctness):
Because they are NOT ambiguous. In order to be ambiguous the methods need to have the same signature. The fact that the string message parameter has a default value of null effectively creates BEHAVES as though it creates two callable overrides, one of which HIDES the original method, and one of which is distinctly callable with a string.
You are effectively doing creating the same behavior as if you were to do this:
public class RestController : ApiController
{
protected new OkResult Ok()
{
return Ok(null);
}
protected OkResult Ok(string message)
{
// Do your thing...
}
}
You will find there is no way to directly call ApiController.Ok() from PersistenceRestController.
If you want to call ApiController.Ok() from RestController, you'll have to use the base keywoard: base.Ok();
While #DimitarTsonev and #Dusty are telling true stuffs, but your answer is something between their answers. Here, you have inheritance situation. See these classes:
public class Foo {
public void Bar() {
}
}
public class Foo2 : Foo{
public void Bar(string message = null) {
}
}
public class Foo3 : Foo2{
public void Test(){
Bar();
}
}
When you call Bar() in your Foo3 class, the runtime will lookup after the method inside the Foo3 class. If found it, execute it, otherwise go to the top class: Foo2 and look after Bar method. Is there any? yes! so execute it! that's why when you call Ok, your RestControllers' version get executed.
But also, the Foo2.Bar(string message = null) will not conflict with Foo.Bar() because they are NOT ambiguous as #DimitarTsonev said. So, your code will work just fine.
AND, what about calling Foo.Bar() from Foo3? You have to use casting here:
public class Foo3 : Foo2 {
public void Test() {
Bar(); // this will execute Foo2.Bar()
}
public void Test2() {
((Foo)this).Bar(); // this one will execute Foo.Bar()
}
}
public class Foo
{
public void Bar()
{
}
public void Bar(string message = null)
{
}
}
Those are two different methods because the second has the optional argument.
However, please note that the second method called with no arguments will actually execute the first one, which may produce some unexpected behaviour.

Method overriding or interception

In my project, I have many DLL assemblies referenced. One of those DLL's contains the bool method that I want to change. I do not have the original source for the DLL and using a Reflector to decompile a project seems impractical. All I want to do is intercept or override this method or method call so that I can change it's return value to match my own method outside of said DLL.
Any such way to do this? Thanks!
Edit:
Here is an example:
public virtual bool isOwner()
{
return false;
}
Essentially, I just want to change getOwner to return true;
If the class is public and the method is marked as virtual, then you can simply override it with this syntax:
public MyClass : TheClass
{
public override ReturnType MethodName(Arguments)
{
//class the base class implementation if needed
//base.MethodName(Arguments)
//do your own stuff and return whatever is needed
}
}
Hope this helps
EDIT: A word of caution though, this won't replace the calling code within the DLL. It will only work if you instantiate the derived class yourself and call it from your code.
Is there a general way to do what you want, built into .NET?
Yes, and no.
If you want every usage of class X' method Y to be replaced by some other code, then no, there is nothing built into .NET class system or compiler that will do this.
If you can inherit from class X, overriding method Y, and then ensure that all places where class X is used, your new class is used instead, then yes, that is the proper way to do this.
This is easily done:
public class YourFixedClass : TheProblematicClass
{
public override string YourProblematicMethod()
{
// probably call the problematic method through base.
// and fix the return value, or fix the parameters
// or don't call it at all, re-doing whatever it does
}
}
Or, if you can make a new class that implements all the same interfaces, wrapping (delegating) all the methods and properties of the original (problematic) class, then that might be doable, but this requires all actual usage of the class to go through the interfaces.
As this:
public class Wrapper : IInterface1, IInterface2
{
private readonly YourProblematicClass _C;
public Wrapper(YourProblematicClass c)
{
_C = c;
}
public string YourProblematicMetho()
{
// probably call the problematic method through _C.
// and fix the return value, or fix the parameters
// or don't call it at all, re-doing whatever it does
}
}
If, on the other hand, you don't have control of where all the code is that calls the class/method, then no, you can't do any of this.
So what else is there? Well, there is always the debugger interfaces. You can make a program that is somehow the debugger of itself, patching in the right code upon demand, but this is likely to be extraordinary difficult to get right.
In short, no, there is no way to do what you want. You need to find a different way to accomplish this.
Have you thought about changing the original assembly in the first place? I understand that you don't have the source code for it, but is that because:
You lost it
You didn't make it
In point 1, I would really work towards recreating the source code, either through a decompiler or similar, and get a new project going to fix that.
In point 2, have you thought about contacting the people that made it and asking them for help?
Uhm Ok you can do something like this:
public class MyNameClass : MyDllname.MyClassName
{
public bool isOwner()
{
return !base.isOwner();
}
}
Then you have override the method and you can use all the other methods in the DLL simply using an istance(if there aren't static) of the MyNameClass
You can use "new" modifier.
See example on http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
Or this:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new ClassA().IsEvenDayToday()); // Result: true
Console.WriteLine(new ClassB().IsEvenDayToday()); // Result: false
Console.ReadKey();
}
}
public class ClassA : ClassB
{
public new bool IsEvenDayToday()
{
return DateTime.Now.Day % 2 == 0;
}
}
public class ClassB
{
public bool IsEvenDayToday()
{
return DateTime.Now.Day % 2 != 0;
}
}

Declare a function supporting both Void and IEnumerator

I was wondering if there is a way to declare a method (in an interface for example) that supports the use of IEnumerator and Void, without the need to implement both in the subclasses?
public void Start()
public IEnumerator Start()
this is related to my other question: Hold or Wait while Coroutine finishes
i noticed in the Unity context, the default Start() method seems to allow for both.
You can't do that because those methods would have the same signature and the CSC woudn't be able to figure out which method should be statically bound for each call. e.g.:
public class TestClass
{
public int FooMethod()
{
return 1;
}
public void FooMethod()
{
return;
}
public string FooMethod()
{
return "foo";
}
}
static void Main()
{
TestClass test = new TestClass();
Console.WriteLine(test.FooMethod()); // which FooMethod should be called here?
}
A method's return type is not considered as part of its signature. What you can do is overload the same method with a different signature to return a different type. Also, in the case of an additional method that differs only in returning void, you can always choose not to use the result returned by the original method.
The case with interfaces is similar. when a class implements an interface it is agreeing to a protocol, that it implements that interface's behaviour which is what consumers of your class expect. So you cannot partly agree with an interface. Although you can throw a NotImplementedException in your implementations you have to at least define all members, which leads to the same problem mentioned in the above example: the C# compiler will not be able to statically bind your method calls and your code will fail to compile.
You can solve your problem by reconsidering your design.
The short answer is no.
The closest you could get to this is using generics, however that would not work for a void, sorry.
public T Start()
One function name + combination of parameters can only be declared once, thus can only have one output.

Categories