Method call that call method from other object - c#

I was wondering if it's possible to otain such behaviour where method call of one object will call method of another object.
public class Example
{
public void DoSomething() { /*BASICALLY NOTHING*/ }
}
public class Engine
{
public void DoSomething() { Console.WriteLine("bleee"); }
static void Main()
{
Example e = new Example();
Engine eng = new Engine();
e.DoSomething = eng.DoSomething;
}
}
My Example object is exactly dummy object, but I would like to use this class as base class and build on top of it something more fancy.
So e.DoSomething() should call method from eng.DoSomething(). I can't use inheritance or pass Engine object to Example as argument.
Is it possible? How to achieve that? Is such approach used somewhere?

You can't do this in the way you describe, but you can do it with delegates.
public class Example
{
public Action DoSomething {get; set;}
}
public class Engine
{
public void DoSomething() { Console.WriteLine("bleee"); }
static void Main()
{
Example e = new Example();
Engine eng = new Engine();
e.DoSomething = eng.DoSomething;
}
}
Now you can say e.DoSomething() and it will call via the delegate by calling the getter and then calling the returned action.

Using reflection we can do the method call with same type info. But other types method is not possible. I think so.

Related

How to determine wether it is better to create an object on method or on object

I was wondering how I should decide to create an object, on method or class instance.Below a few examples to clarify. I want to the best approach to know how I should determine to choose between example 1 and 2.
IMPORTANT: Consider this a Windows Service (SVC) hosted in IIS.
Example 1
public class mySvcService
{
ReusableClass rClass = new ReusableClass();
public void MethodOne()
{
//Do Method One Stuff...
rClass.doSomething();
}
public void MethodTwo()
{
//Do Method Two Stuff...
rClass.doSomething();
}
}
public class ReusableClass
{
string valueOne;
string valueTwo;
string valueThree;
public void doSomething()
{
//DoSomeWork
}
}
Example 2
public class mySvcService
{
public void MethodOne()
{
ReusableClass rClass = new ReusableClass();
//Do Method One Stuff...
rClass.doSomething();
}
public void MethodTwo()
{
ReusableClass rClass = new ReusableClass();
//Do Method Two Stuff...
rClass.doSomething();
}
}
public class ReusableClass
{
string valueOne;
string valueTwo;
string valueThree;
public void doSomething()
{
//DoSomeWork
}
}
It is all about state. Will the object preserve some state between the two method calls, or even within the method, or not? If so, you should keep the object alive. Else, you can create a new object every time you call the method, or maybe even make the method static if there is never any state involved.
So:
Class preserves state that should be kept across methods: make a class variable or pass the object along the methods.
Class preserves state that should be kept within the same method: make a local variable.
Class doesn't preserve any state: make the method static, no instance needed.
The golden rule is to keep the scope as local as possible. From the second example if you are going to use doSomething() everywhere then it is better to create it once and have class level scope. If you need doSomething() only in one method, create the object locally within the method.
It is better to leave it inside of a method. Usually, it is being done inside of the constructor. This has the favor that it can incorporate a factory for different scenarios, or that it can be easily injected. I would strongly suggest to separate the responsibilities of the properties and let them be used as needed.
If you want to limit the scope of the object to a method, It can be done by using "Method injection" as shown below. You can use the other setter and constructor injection methods if the scope of the object is through out the class.
public interface IReusable
{
void doSomething();
}
public class Reusable: IReusable
{
public void doSomething()
{
//To Do: Some Stuff
}
}
public class mySvcService
{
private IReusable _reuse;
public void MethodOne(IReusable reuse)
{
this._reuse= reuse;
_reuse.doSomething();
}
public void MethodTwo(IReusable reuse)
{
this._reuse= reuse;
_reuse.doSomething();
}
}

Is it possible to determine which instance of a class the current instance of a class is instantiated from?

As the title suggests, it is possible to determine which instance of a class a particular instance of another class is instantiated from?
Update: Example Code below
class FooBar: Foo
{
private Context context;
public FooBar(Context _context): base(_context)
{
this.context = _context;
}
}
class Foo
{
public Baz baz;
private Context context;
public Foo(Context _context)
{
baz = new Baz();
this.context = _context;
}
}
class Baz
{
public Baz()
{
GetNameOfCaller()
}
private void GetNameOfCaller()
{
....
....
_className = ....;
}
private string _className;
}
Yes, you can do that for constructors the same way as for regular methods. Just use the CallerMemberName to pass in the name of the calling method. You won't have the class name with it, then you need to walk the StackTrace which is much more complicated.
public class X
{
public X([CallerMemberName] string caller = null)
{
this.Caller = caller;
}
public string Caller { get; private set; }
}
Then just call this. The compiler will fill in the caller parameter for you:
static void Main(string[] args)
{
X x = new X();
Console.WriteLine($"Caller = {x.Caller}"); // prints Main
}
You could use System.Diagnostics.StackTrace:
public class Foo
{
public void MethodBah()
{
System.Diagnostics.StackTrace t = new System.Diagnostics.StackTrace();
MethodBase callingMethod = t.GetFrame(1).GetMethod();
Type callingMethodType = callingMethod.DeclaringType;
string className = callingMethodType.Name;
}
}
Works even in .NET 1.1.
With your (updated) example you have to use t.GetFrame(2).GetMethod() instead of GetFrame(1) to get FooBar instead of Foo because the child- calls the parent constructor.
I believe that your requirement should be solved using aspect-oriented programming.
OP said in some comment:
[..] Logging purposes for now but may not be limited to it alone [...]
For example, there's an extremely powerful tool called PostSharp which lets you intercept any method call, when it's being called and after it was called:
[Serializable]
public class LogAspect : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
}
public override void OnExit(MethodExecutionArgs args)
{
}
}
Now you can apply the whole aspect as a regular attribute to a method, class or even to an assembly (thus, all methods within the assembly will be loggable).
You can access called method through MethodExecutionArgs.Method (which is of type MethodBase, and this means that you can access which type declares the whole method through MethodBase.DeclaringType.
With a tool like PostSharp you are adding an extra compilation step, but it has the great advantage that your interceptions are injected during compile-time. That is, it will perform like adding the whole code manually in every method.
You can also implement the same thing creating run-time proxies using Castle DynamicProxy to intercept method calls.

Error when doing simple event\delegate calls when generic class is involved

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.

C# - How to pass and run a method in a function?

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);
}

Can a delegate be used to call a method of a class without instantiating it?

An interviewer asked me that he has got a heavy class with a number of methods.
He needs to have just one method as of now.
He asked me if Delegates in C# can help me calling that method without instantiating the class?
And he said Yes delegates can help us in this way.
I googled it. I tried running it on my VS but I guess I will need to initialize the class.
Have a look at this snippet -
public class HomeController : Controller
{
public ActionResult test()
{
NumberChanger nc1 = new NumberChanger( /*what to do here!
can i call sum method of class abc*/);
return View();
}
}
public delegate int NumberChanger(int n, int m);
public class abc
{
int a;
int b;
public int sum(int a, int b) {
return a + b;
}
}
If you need to use non-static method, probably you should use new NumberChanger(new abc().sum)
Have a try
You always need at least 1 instance to call an instance method.
But if you want to avoid creating lots of heavy objects, you could use a trick like this:
class TestClass
{
private static TestClass DummyInstance;
public static Action GetShowAsDelegate()
{
DummyInstance = DummyInstance ?? new TestClass();
return (DummyInstance.Show);
}
public void Show()
{
Console.WriteLine("It works!");
}
}
class Program
{
static void Main(string[] args)
{
var show = TestClass.GetShowAsDelegate();
show();
}
}
Your class stores a private static instance of itself, which is instantiated when the caller asks for a delegate version of Show(). It then uses that instance, so you don't need to create one externally each time. After the first call, anyone can run the Show method by getting a delegate, without the need to create any more instances.

Categories

Resources