I'd like to use inline interface implementation in C# but reading some posts like this or this I found out that it's not like Java do it.
Supposing this interface:
public interface MyListener {
void onHandleOne();
void onHandleTwo();
}
and I pass this interface as a parameter:
myMethod(MyListener listener){
//some logic
}
and when I call it I'd like to do inline imlementation like in java:
myMethod(new MyListener () {
#Override
public void onHandleOne() {
//do work
}
#Override
public void onHandleTwo() {
//do work
}
});
As an alternative I made a class that implements yhis interface and use this class to call my method:
public class MyImplementor : MyListener {
public void onHandleOne() {
//do work
}
public void onHandleTwo() {
//do work
}
}
and call my method: myMethod(new MyImplementor())
but this solutions needs a new class every time I'll call this method (for different behavior) maybe is there a way using lambda or somehow to do it like:
myMethod(new MyImplementor() =>{//handle my methods})
but this solutions needs a new class every time I'll call this method
(for different behavior) maybe is there a way using lambda or somehow
to do it like
Yes, give it a delegate parameter and pass it a lambda.
public class MyImplementor : MyListener
{
private readonly Action handle1;
private readonly Action handle2;
public MyImplementor(Action handle1, Action handle2)
{
this.handle1 = handle1;
this.handle2 = handle2;
}
public void onHandleOne()
{
handle1();
}
public void onHandleTwo()
{
handle2();
}
}
Then you can use it as
myMethod(new MyImplementor(()=>{//handle method1}, ()=>{//Handle method2});
Related
I've got a design question.
I've got a static class used in some old code that calls a static method to run some operation. If a certain condition is met, I want to call another method right after it.
I wanted to use the decorator pattern but I can't exactly return an instance of the static class if the condition is not met.
This is what's happening now.
var result = StaticClass.DoSomething(some parameters);
What I want is to write to a database right after that DoSomething is called if another variable is true and I didn't want to just pile on to the old code with conditionals so I'd rather delegate that to some other class. This is what I really want to do.
var result = StaticClassFactory(condition).DoSomething(some parameters);
Class1
void DoSomething(parameters) {
StaticClass.DoSomething()
}
Class2
void DoSomething(parameters) {
StaticClass.DoSomething();
DoSomethignElse();
}
Any suggestions?
What you can do is use an interface to represent the "doer":
public interface IDoer
{
void DoSomething(object parameters);
}
Then create the two classes:
public class DefaultDoer : IDoer
{
public void DoSomething(object parameters)
{
StaticClass.DoSomething(object parameters);
}
}
public class AugmentedDoer : IDoer
{
public void DoSomething(object parameters)
{
StaticClass.DoSomething(object parameters);
DoSomethingElse();
}
}
Then use a factory to return an instance that implements IDoer based on the condition:
public class DoerFactory
{
public IDoer GetDoer(object someCondition)
{
//Determine which instance to create and return it here
}
}
I used placeholders of type object for some things as no more information is available.
Is there a way to modify the behavior of a static method at runtime?
for example:
Say I have this class
public class Utility {
public static void DoSomething(string data){
//...
}
}
Is there a way to do something like this:
typeof(Utility).SetMethod("DoSomething", (data) => { /*Do something else...*/ });
Such that if you call Utility.DoSomething it executes the new code?
What you want to do is pass the behavior you want as another parameter into the function.
public static void DoSomething(string data, Action<string> operation)
{
operation(data);
}
This is an oversimplified example, of course. What you actually wind up doing in your own code is going to depend on what operation actually does.
If you're trying to modify the behavior of an existing, compiled, in-production method, and cannot overload or override the method in the usual ways, the only way I know of to do that is CIL Rewriting, possibly using an Aspect Weaver.
Sure.
public class Utility {
public static Action<String> _DoSomething;
public static void DoSomething(string data){
if (_DoSomething != null) {
_DoSomething();
return;
}
// default behavior here.
}
}
And to mask the default behavior:
Utility._DoSomething = (data) => { /* do something else */ };
I don't see why you wouldn't just create a new class that inherits from Utility and define a new function that does what you want.
public class Program
{
static void Main(string[] args)
{
if (true)
{
Utility.DoSomething("TEST");
} else
{
Util1.DoSomething("TEST");
}
}
}
public class Utility
{
public static void DoSomething(string data)
{
//Perform some action
}
}
abstract class Util1 : Utility
{
public static new void DoSomething(string data)
{
//Perform a different action
}
}
I think although it is possible to do this you should ask yourself: "Why do I need this functionality"? Usually a method stays as is, and does what it is supposed to do according to its interface which is given by its name and signature. So while you can add additional logic by adding an Action<T>-parameter to your signature you should ask yourself if this won´t break the contract of the interface and therefor what the method was designed for.
Having said this you should consider either overwrite your method if the functionality you need is some kind of "making the same things differently then the parent-class" or extend it by adding a dependency into your consuming class and add some methods to that class that extent the functionality provided by the contained class (see also favour composition over inheritance)
class MyClass {
Utility MyUtility;
void ExtraMethod() { /* ... */ }
}
EDIT: As you´re using a static method the opportunity on overwriting is obsolete. However IMO that sounds like a great design-flaw.
The following classes
public class PagedItemList<T>
{
public delegate void PageChanged(int newPage);
public event PageChanged PageChangedEvent;
}
public class SomeClass
{
public void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(NotifyPageChanged);
}
public void NotifyPageChanged(int newPage) { }
}
Throws the error:
InvalidCastException: Cannot cast from source type to destination type
When I try to add a listener to the event as seen in the example above.
The call to SetupWithPagedList is correctly parametrized:
obj.SetupWithPagedList<Monster>(pagedMonstersList)
I have done events and delegates a lot before, the only difference here is that there is a <T> involved in this class. Has anyone had issues doing events and delegates with templates?
I think your problem in this case is with, the instances. The first question I made when I saw your PagedItemListCode was, why SetupWithPagedList is not an static method, and I checked that you are calling the NotifyPageChanged method in the instance of the class. I do not know the logic behind the problem, but maybe the right way is like this:
public static void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(list.NotifyPageChanged);
}
Note that the instance of the class maybe is not the same instance of the object that is passed to the SetupWithPagedList method. Maybe the class is PagedItemList<A> and the method parameter is PagedItemList<Monster>. Maybe the class do not need to be generic. Check it.
EDIT
I tried your code and works perfect:
var p = new PagedItemList<int>();
var sc = new SomeClass();
sc.SetupWithPagedList(p);
p.RaisPageChanged(5);
...
public class PagedItemList<T>
{
public delegate void PageChanged(int newPage);
public event PageChanged PageChangedEvent;
public void RaisPageChanged(int page)
{
if (PageChangedEvent != null)
PageChangedEvent(page);
}
}
public class SomeClass
{
public void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(NotifyPageChanged);
}
public void NotifyPageChanged(int newPage)
{
Debug.WriteLine("Page: ",newPage);
}
}
Check it, maybe is something else.
I'm trying to write a wrapper for a Selenium test that re-runs the test if it fails, I've got the mechanics working fine. But I need to figure out a way of passing either a function/method or (preferably) multiple methods inside of the function. Here's an example of what I want to achieve:
In the wrapper class:
public class TestRunner{
public void RunTest(function FuncToRun){
FuncToRun();
}
}
In the test:
public class Tests{
public void Test(){
...Run test methods...
}
TestRunner.RunTest(Test());
}
This is purely for demonstration. I know that this doesn't work, but I hope it will convey my point to you.
Looks as though you need a delegate.
An applicable delegate for your scenario is the Action delegate which can be used to represent a single parameterless method.
public class TestRunner
{
public void RunTests(params Action[] tests)
{
foreach (var test in tests)
{
test.Invoke();
}
}
}
Note the use of the params keyword which will allow you ro supply any number of tests to the RunTests method. Here is an example using an implicit method group conversion:
public class Tests
{
public void TestOne() {
}
public void TestTwo() {
}
}
...
var runner = new TestRunner();
var tests = new Tests();
runner.RunTests(tests.TestOne, tests.TestTwo);
You could use Action parameters to do this
public class TestRunner{
public void RunTest(Action FuncToRun){
FuncToRun();
}
}
public class Tests{
public void Test(){
...Run test methods...
}
TestRunner.RunTest(() => Test());
}
You want to do something like this. But need more context as in inputs and what return value you are expecting.
Func<string, int> myMethodName
This is an example of usage:
public bool RunThisMethod(Func<string, int> myMethod)
{
//... do stuff
int i = myMethod("My String");
//... do more stuff
return true;
}
use delegate . simply declare a delegate to the method you want to pass and call and assign the method to it.
http://msdn.microsoft.com/en-IN/library/ms173171.aspx
You may use delegates or even Action or Func objects.
public class TestRunner{
public void RunTest(Action funcAction){
funcAction();
}
}
public class Tests{
public void Test(){}
TestRunner.RunTest(Test);
}
I know the question can be answered by saying foreach(var item in items){item.doSomething()}; but what i'm after is slightly different. Here is the interface.
ManagableClass .cs
public interface ManagableClass : System.IDisposable
{
void Initialize();
}
and below is how I would like to see my code look like
MainManagerClass.cs
public class MainManagerClass: ManagableClass
{
private List<ManagableClass> minions;
public void Initialize()
{
TellMinionsTo(Initialize);
}
public void Dispose()
{
TellMinionsTo(Dispose);
}
private void TellMinionsTo(Action doSomething)
{
foreach (ManagableClass minion in minions)
{
minion.doSomething();
}
}
}
I know that this code that is here will not work, but it seems like this should be doable in C#. Anyone know if this can be done? If not it's not like it's the end of the world, I'll just do a foreach in each method.
The problem with your code is that you pass a delegate to a method of a certain instance (yourself), while what you want is to invoke a certain method on all minions.
You can use lambda expressions, something like
public void Dispose()
{
TellMinionsTo(minion=>minion.Dispose());
}
private void TellMinionsTo(Action<ManagableClass> doSomething)
{
foreach (ManagableClass minion in minions)
{
doSomething(minion);
}
}
I don't like using List's method directly. Tomorrow you'll have to work via an interface and your IList may not have to be a List at all.
What you are looking for is a Composite pattern. This pattern will allow you to have a class that will implement the correct method and differ it to a list of items. However, in your case, you need to modify your interface to implement the DoSomething() method. So, instead, this should look like this.
public interface ISomething
{
void DoSomething();
}
public class SomethingManager : ISomething
{
private List<ISomething> _items = new List<ISomething>();
public void DoSomething()
{
_items.ForEach(i => i.DoSomething());
}
}
Is that what you are looking for ?