How can I assign a new action to an existing method? - c#

I've created a class in C# which uses the method "Action".
public void Action()
{
}
The method is empty because, when a new instance of the class is created, the user should be able to define what the method does. One user may need the method to write to the console, another may want it to assign a value to a variable, etc. Is there any way for me to change what the method can do outside of its original definition, along the lines of the following:
//Using the instance "MyClass1", I have assigned a new action to it (Writing to the console)
//Now the method will write to the console when it is called
MyClass1.Action() = (Console.WriteLine("Action"));

Is there any way for me to change what the method can do outside of
its original definition
Not via "Named Methods" and the way you're using them in your example. If you want your class to be able to invoke a unit of execution defined by the user, you need to look either into inheritance hierarchy (as specified in #CodeCaster answer via virtual methods and overriding them), or perhaps look into delegates.
You can use an Action delegate:
public Action Action { get; set; }
Use it like so:
var class = new Class();
class.Action = () => { /*Code*/ }
And, when you want to invoke it:
if (class.Action != null)
{
class.Action();
}

By making it abstract, inheriting the class and overriding the method.
public class FooBase
{
public abstract void Bar();
}
public class Foo1 : FooBase
{
public override void Bar()
{
// Do something
}
}
public class Foo2 : FooBase
{
public override void Bar()
{
// Do something else
}
}

Related

How to get the name of the instance disposed by using reflection

I am building some integration tests for my database stored procedures.
I have setup an xUnit project and implemented Fixture pattern. To show you:
public class MyTableTest : IClassFixture<DatabaseFixture>
{
public MyTableTest()
{
//DO SOMETHING
}
[Fact]
public void Test()
{
//DO SOMETHING
}
}
And:
public class DatabaseFixture : IDisposable
{
public void Dispose()
{
// ... clean up test data from the database ...
}
}
This DatabaseFixture is something that will be shared among all of my test classes. Why? Because I want some common logic happening at the end of every test, such as cleanup.
Point is that I need to know which table to clean, which in my example would be MyTable. Such information I would retrieve by using reflection when the Dispose method will run against the instance of MyTableTest being disposed . How can I achieve this? Is it even possible (and correct) trying to achieve this? Thanks in advance.
You can have a TableName property in the DatabaseFixture class. Then receive an instance of the class in constructor of your test classes and set that TableName property. Later you can use it in dispose to do some cleanup.
public class MyTableTest : IClassFixture<DatabaseFixture>
{
DatabaseFixture databaseFixture;
public MyTableTest(DatabaseFixture databaseFixture)
{
this.databaseFixture = databaseFixture;
databaseFixture.TableName = "MyTable";
}
[Fact]
public void Test()
{
}
}
public class DatabaseFixture : IDisposable
{
//...
public string TableName { get; set; }
//...
public void Dispose()
{
// Cleanup based on TableName
}
}
To learn more about sharing context in xUnit, take a look at:
Shared Context between Tests
Comparing xUnit.net to other frameworks
You can use custom attributes to attach any arbitrary data to your derived Fixture class.
For example
you can create a TableNameAttribute like this:
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class TableNameAttribute : Attribute
{
public string Name { get; }
public TableNameAttribute(string name)
{
this.Name = name;
}
}
you can apply this attribute to your derived fixture class:
[TableName("MyTable")]
public class MyTableFixture : DatabaseFixture { }
you can use that fixture class inside your test
public class MyTableTest : IClassFixture<MyTableFixture>
{
[Fact]
public void Test()
{
//DO SOMETHING
}
}
Finally this is how you can retrieve the Name from the Dispose method:
public abstract class DatabaseFixture : IDisposable
{
...
public void Dispose()
{
var attribute = this.GetType().GetCustomAttribute(typeof(TableNameAttribute));
if (attribute is TableNameAttribute tableNameAttr)
Console.WriteLine(tableNameAttr.Name);
}
}
Is it even possible (and correct) trying to achieve this?
No. Reflection cannot tell type T in what context T is used; reflection only sees T's declaration.
More specific to your situation, reflection cannot tell type DatabaseFixture that it is being used as a type parameter of generic interface IClassFixture in the declaration of MyTableTest. In other words, for this set of declarations,
class A { }
class B <T> { }
class C : B<A> { }
A cannot reflectively determine that it is used in C's declaration, but C can know about its usage of A:
typeof(C)
.BaseType // B
.GetGenericArguments()[0] // A
How can I achieve this?
Depending on how you are using DatabaseFixture, you could get the calling test class using the StackTrace (if you are really bent on using reflection). Here is a simple example:
public class DisposableObject : System.IDisposable
{
public void Dispose()
{
var stack = new System.Diagnostics.StackTrace();
// This will log the name of the class that instantiated and disposed this.
System.Console.WriteLine(stack.GetFrame(1).GetMethod().DeclaringType.Name);
return;
}
}
If your DatabaseFixture is not called directly from your test class, you will either have to know the offset to pass to GetFrame(int), or you will need to search each frame until you find the first DeclaringType that matches your requirements (e.g., BaseType is IClassFixture with Generic Argument DatabaseFixture), something like this:
System.Type testClassType = new StackTrace()
.GetFrames()
.Where(f =>
{
System.Type baseType = f.GetMethod().DeclaringType.BaseType;
return typeof(IClassFixture<DatabaseFixture>).IsAssignableFrom(baseType);
})
.FirstOrDefault() // First matching result (assuming you found any)
?.GetMethod() // Get the reflected Method
.DeclaringType; // Get the type (e.g. class) that declares this method.
string tableName = testClassType.Name.Replace("Test", "");
Otherwise, you will need to set the table name manually, as suggested by Reza and Peter.

How to use Activator.CreateInstance() to call an override C#

I am looking to find the proper way to call a overridden function of an inherited class using the Activator.CreateInstance() function. I am doing this so that I can call a specific function of a derived class based on a string object, such that the string determines which derived class object will be created and have its function called. Something like this but I do not know how to do it properly or if there is a better way than using Activator.
public class Test
{
public virtual void DefaultCalibration()
{
//Do nothing
}
}
public class EasyTest : Test
{
public override void DefaultCalibration()
{
//Do one thing
}
}
public class HardTest : Test
{
public override void DefaultCalibration()
{
//Do another thing
}
}
public class Tester
{
public void main()
{
string testName = "";
// ...
// ... Do some stuff to get a string of the name of the class, ie testName = "HardTest";
// ...
Type type = Type.GetType(testName);
object instance = Activator.CreateInstance(type);
((Test)instance).DefaultCalibration(); //this line doesn't call the derived function
}
}
I want it so that the derived class' override function is called instead of the base class function.
The intent being that if my string is "HardTest", then it would essentially look like
((HardTest)instance).DefaultCalibration();
but if it was "EasyTest" then it would look like
((EasyTest)instance).DefaultCalibration();

Best way to share a function between two class files

There are two files A.cs and B.cs. There is a method fn() which is used in both the classes.
Method fn() is used in both class files. This increases code complexity if I need this method in many class files (say 100 files).
I know that we can call this method by creating an object for the class in which this method is defined. How can I share this function between two or more classes without creating an object every time for accessing this method?
Put the method in a static class:
public static class Utils
{
public static string fn()
{
//code...
}
}
You can then call this in A.cs and B.cs without creating a new instance of a class each time:
A foo = new A();
foo.Property = Utils.fn();
Alternatively, you could create a BaseClass that all classes inherit from:
public class BaseClass
{
public BaseClass() { }
public virtual string fn()
{
return "hello world";
}
}
public class A : BaseClass
{
public A() { }
}
You would then call fn() like so:
A foo = new A();
string x = foo.fn();
I hope the function isn't really called fn(), but actually named to what it does, like CalculateTotal(). Then you can extract this method into a class, say: TotalCalculator.
Now upon application startup, preferably using dependency injection, you create one instance of the class that gets shared between objects that require it. Like so:
class TotalCalculator
{
public int Calculate()
{
return 42;
}
}
class NeedsCalculator1
{
TotalCalculator _calculator;
public NeedsCalculator1(TotalCalculator calculator)
{
_calculator = calculator;
}
public void Foo()
{
_calculator.Calculate();
}
}
class NeedsCalculatorToo
{
TotalCalculator _calculator;
public NeedsCalculatorToo(TotalCalculator calculator)
{
_calculator = calculator;
}
public void Bar()
{
_calculator.Calculate();
}
}
Then you instantiate the calculator once, and pass it into the other classes' constructor:
TotalCalculator calculator = new TotalCalculator();
NeedsCalculator1 dependency1 = new NeedsCalculator1(calculator);
NeedsCalculatorToo dependency2 = new NeedsCalculatorToo(calculator);
You can now further abstract the calculator dependency by creating a base class containing the constructor and a protected TotalCalculator instance field, for example.
Assuming that this method is self contained, you could create a static class and put this method as a static method in it, which is in turn, called by the other classes.
If is is not self contained, you could try and declare it in some super class and let the other 100 classes extend that class.

How to call top class constructor?

I hope I can explain this problem right, it's a bit confusing for me.
I have been working on a game library similar to flixel but, using C#'s XNA framework instead of Flash. Right now the current class layout is something like this.
ClxBasic -> ClxObject -> ClxSprite
Each class has a constructor and calls the constructor for the class below it. I use this code to do this.
namespace Test
{
public class ClxBasic
{
public ClxBasic()
{
Constructor();
}
public void Constructor()
{
DoSomething();
}
}
public class ClxObject : ClxBasic
{
public ClxObject() : base()
{
Constructor();
}
public void Constructor()
{
DoSomething();
}
}
public class ClxSprite : ClxObject
{
public ClxSprite() : base()
{
Constructor();
}
public void Constructor()
{
DoSomething();
}
}
}
So basically when I create a new ClxSprite it calls the ClxSprite constructor, then all the ones below it (ClxObject and ClxBasic).
I'm sure there is an easier way to do this and I am all ears.
However, my bigger issue is actually how to properly derive and override methods from the other classes.
The issue is that when creating a class that extends from ClxSprite, for example, when calling a method that was overridden from the most basic class (ClxBasic), it will only call the bottom method and not the top.
The reason I need to do this is because I have a global class which keeps control of all the objects derived from ClxBasic by adding themselves to a list in the ClxBasic constructor.
Here's some example code.
namespace Test
{
public static class ClxG()
{
public static List<ClxBasic> GlobalObjects; //All objects will be added here by the ClxBasic constructor
ClxSprite test = new ClxSprite();
GlobalObjects.Add(test);
public static Update()
{
foreach(ClxBasic basic in GlobalObjects)
basic.Update(); //Calling this calls ClxBasic.Update() when it should call ClxSprite.Update()
}
}
}
When calling basic.Update() it goes to the bottom Update, the one located in ClxBasic, despite the object being a ClxObject or ClxSprite or other derived class.
I have a limited fix as well, by changing the ClxBasic to ClxSprite in the foreach loop, you can call that classes constructor method properly. However, when making custom classes based off of the library who override a method, the lower Update is called.
However, the limit is that you can't add classes I didn't specifically plan for. For example, if I were to derive a class Player from ClxSprite and, override the Update() method, it would get added to the GlobalObjects list but, never have it's update called, the highest it will go is ClxSprite's.
The way I want it to work is, in Game1.cs I want to just be able to put FlxG.Update() in the Game.Update() loop and just be able to create the object and have my framework handle the rest.
I hope I've made a bit of sense, the whole thing feels like some sort of inheritance inception and kind of makes my brain hurt.
To also call a base class method as part of a child class implementation, you'd do this:
class Base {
public virtual void Method() {
// ...
}
}
class Derived : Base {
public override void Method() {
base.Method();
// ....
}
}
class Derived2 : Derived {
public override void Method() {
base.Method();
// ....
}
}
But the child method is not required to call the base one.
Constructors, on the other hand, are always required to (ultimately) call a base constructor.
Now, if you want a base class method to always be called as part of some processing, you can employ the template method pattern. Basically your base class has a non-virtual method that drives an algorithm that calls virtual (or abstract) methods; which the child classes can override to create their own versions.
You are properly using base() to call the constructors of your base classes. As for how you are defining your constructors, why is Constructor() a separate method, rather than the body of the different constructors? If you are only planning on calling Constructor() when you create a new insance of one of your classes, I would recommend moving Constructor() back into your actual constructors, like so:
namespace Test
{
public class ClxBasic
{
public ClxBasic()
{
// Do Something
}
}
public class ClxObject : ClxBasic
{
public ClxObject() : base()
{
// Do Something
}
}
public class ClxSprite : ClxObject
{
public ClxSprite() : base()
{
// Do Something
}
}
}
As for being able to call the appropriate Update() function, depending on the actual class of your object, you would accomplish this using the virtual and override keywords. You would use them like so:
namespace Test
{
public class ClxBasic
{
// Define the base function that can be overridden
// in subclasses.
public virtual void Update()
{
// Do Some Updates
}
}
public class ClxObject : ClxBasic
{
// We're overridiung the base function, so we
// must mark this function as an override.
public override void Update()
{
// Do Some Updates
}
}
public class ClxSprite : ClxObject
{
// We're overridiung the base function, so we
// must mark this function as an override.
public override void Update()
{
// Do Some Updates
}
}
}
When you call Update() on an object that is an instance of a class derived from ClxBasic, the top-level Update() function in that objects inheritance-chain will be called. For instance:
ClxBasic clxBasic = new ClxBasic(); // Calls ClxBasic.Update()
ClxBasic clxObject = new ClxObject(); // Calls ClxObject.Update()
ClxBasic clxSprite = new ClxSprite(); // Calls ClxSprite.Update()
In addition, if you want your Update() functions to call the Update() function of their parent, you can use the base keyword.
For example:
public class ClxSprite : ClxObject
{
// We're overridiung the base function, so we
// must mark this function as an override.
public override void Update()
{
base.Update(); // Will call ClxObject's Update() function
// Do Some Updates
}
}
Based on your description, your goal seems to be to achieve polymorphic behavior among different game classes. A better solution is to define an interface that different game classes must implement. Then you can put all of your game objects in one generic container, such as an array list, and then have the master game loop iterate through the object list and invoke each object's update method the method during each overall update. I would design the classes like this:
interface IUpdatable {
void doUpdate();
}
class GameClassA : IUpdatable {
void doUpdate() { // }
}
class GameClassB : IUpdatable {
void doUpdate() { // }
}
etc.
Your goal is to achieve polymorphic behavior among objects of different classes but not necessarily to share data and common functionality. While you can achieve polymorphism through inheritance as well, it is better achieved in this case through simple interfaces and composition.

Call method of the derived class through reflection. Possible or no?

I have a follwing class structure:
public abstract class AbstractFoo
{
public virtual void Prepare()
{
}
}
public class Foo : AbstractFoo
{
public override void Prepare()
{
}
}
public class Bar : Foo
{
public override void Prepare()
{
}
}
public class ClassThatUses
{
public Foo Foo;
}
var classThatUsesInstance = new ClassThatUses { Foo = new Bar (); }
Somehow in ClassThatUses i need to call (through the reflection - mandatory) Prepare method of the class Bar.
Instead of question (???) marks i need to make a reflection code that will call the Prepare method of Bar rather than foo.
Basically, it should be something like:
classThatUsesInstance.GetType.GetProperties()[0]
-> somehow understand that it's actually Bar, but not Foo.
-> call method (which i know how to do, i just need the RIGHT method to be used)
I don't know whether it's Bar, or BarBar, or BarBarBar. I need to find out the REAL type of assigned field rather then type it was casted to.
Is this any possible?
Or is it at least possible to find out the real type of the Foo field in runtime?
p.s. i realize that without reflection it will be called - no problem. this is more of a theory.
UPD: http://msdn.microsoft.com/en-us/library/a89hcwhh.aspx
Note that you cannot use the MethodInfo object from the base class to invoke the overridden method in the derived class, because late binding cannot resolve overrides.
Does that mean the problem is unsolvable?
The GetType method will give you the real type of Foo at runtime:
public class ClassThatUses
{
public Foo Foo { get; set; }
public void CallPrepare()
{
// Foo.Prepare();
Foo.GetType().GetMethod("Prepare").Invoke(Foo, null);
}
}
Following your edit, if you want to find the runtime type of Foo for a particular instance of ClassThatUses then you'll need to use GetValue to interrogate the value of Foo on that instance:
ClassThatUses o = new ClassThatUses() { Foo = new Bar() };
// Type fooType = o.Foo.GetType();
Type fooType = o.GetType().GetProperty("Foo").GetValue(o, null).GetType();
typeof(Bar).GetMethod("Prepare").Invoke(foo, new object[] { });
or
foo.GetType().GetMethod("Prepare").Invoke(foo, new object[] { });
is it at least possible to find out
the real type of the Foo field in
runtime?
Yes, with foo.GetType()

Categories