1

I'm trying to figure out how to do something with c# that I've noticed in particular the Unity engine does. it seems like some form of implementation or subclassing but as I don't have the source I don't know.

in Unity all of the scripts do like this:

class someclass : MonoBehavior
{
}

now there is a list of functions you can use that the engine via this MonoBehavior calls in your classes such as

void OnGUI()
{
  so something here
}

so if you have say 5 scripts that all contain the OnGUI function it gets called in all 5 scripts

I want to implement this type of thing myself but I can't figure this out.

How do you write a Base class or Implementation or whatever this is that calls pre-defined functions in your sub classes but does not require the subclass to the functions and without having to use override in them ?

here is an example source file from unity Engine:

public class EnemyAttack : MonoBehaviour {
    // Use this for initialization
    void Start () {
        AttackTimer = 0;
        CoolDown = 2.0f;
     }
     // Update is called once per frame
     void Update () {
         if (AttackTimer > 0) AttackTimer -= Time.deltaTime;
         if (AttackTimer < 0) AttackTimer = 0;

         if (AttackTimer == 0){
             Attack();
             AttackTimer = CoolDown;
          }
    }
}

that code works perfectly and then engine calls start at first startup (single call) and calls Update every frame notice absolutely NO override is in that code anywhere

it sems to be some sort of event system but I can't find anything on google that describes how to do this.

BrierMay
  • 391
  • 1
  • 4
  • 15

5 Answers5

3

If you do not want/can use the override keyword you could do this by using Reflection (possibly using the dynamic keyword)

The base class 'simply' searches the derived class for specific signatures/attributes and invokes the methods.

If you would write this yourself consider caching the result of the reflection (or use the dynamic keyword that might do the caching for you) and test whether you still get the performance you are after. Reflection can be very slow. See this question too: Dynamic Lang. Runtime vs Reflection

Example:

class TheBehavior
{
    public void Act()
    {
        dynamic derived = this;
        try
        {
            derived.Foo(42);
            derived.Foob(43);
        }
        catch (RuntimeBinderException e)
        {
            Console.WriteLine("Method call failed: " + e.Message);
        }
    }
}

class TheDerived : TheBehavior
{
    public void Foo(int bar)
    {
        Console.WriteLine("Bar: " + bar);
    }
}

class Program
{
    static void Main(string[] args)
    {
        TheBehavior behavior = new TheDerived();
        behavior.Act();
        Console.ReadKey(true);
    }
}
Community
  • 1
  • 1
Emond
  • 50,210
  • 11
  • 84
  • 115
  • @CodeCaster - The question is about an existing library, and the code in the question does not override any existing base class methods. – Lee Mar 15 '13 at 09:10
  • OP says: _"I want to implement this type of thing myself but I can't figure this out."_ – CodeCaster Mar 15 '13 at 09:10
  • @CodeCaster - The question asks how to do it without using `override`. – Lee Mar 15 '13 at 09:14
  • wether it smells or not Unity Game engine does it and I want to do the same thing but every tutorial I find including msdn says you have to use override but yet unity does not so its perplexing me – BrierMay Mar 15 '13 at 09:27
  • @BrierMay - I added to my answer. Although the code given by Lee is correct it might prove to be too slow. Consider using the `dynamic` keyword so the Dynamic Language Runtime is able to cache the results of the reflection. – Emond Mar 15 '13 at 09:34
  • @BrierMay as this answer states it is possible. However you really need to think twice wheter you want to use reflection or `dynamic`, it should only be used as last resort. One of the advantages of OO is that you have compile-time checking of your inheritance and method call structure. – CodeCaster Mar 15 '13 at 09:34
  • I've been using normal events and delegates but I was hoping for something more like the style of Unity where I could simply do like OnConnected as I have one script running lidgren and sending events down to other ones guess I'll stick to plain events and delegates – BrierMay Mar 15 '13 at 09:40
  • Yes, that is a very valid and type safe way. – Emond Mar 15 '13 at 09:44
  • the reason I was looking for doing it without using override is because I have a bas network class using lidgren and as messages of certain types come in I need to pass it off to anywhere from 1 to 30 scripts so they can't override it they just need to have their version called on all of them in succession. – BrierMay Mar 15 '13 at 09:49
  • I like the way unity does it by having the base class just call subclass methods instead of the networkmanager.event += somefunction style – BrierMay Mar 15 '13 at 09:51
1

Since it's not using virtual methods, the most likely method is using reflection. The MonoBehavior class will reflect over its subclasses and search for methods with names which match the right pattern:

public class MonoBehavior
{
    private void InitSubclass()
    {
        var methods = new[] { "OnGUI", "OnLoad" }; //etc
        foreach (string methodName in methods)
        {
            MethodInfo method = this.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
            if (method != null)
            {
                method.Invoke(this, new object[0]);
            }
        }
    }
}
Lee
  • 142,018
  • 20
  • 234
  • 287
0

How do you write a Base class or Implementation or whatever this is that calls pre-defined functions in your sub classes but does not require the subclass to the functions and without having to use override in them ?

From what I understand, those are simply virtual methods. The base class might define some base implementation, but doesn't require derived classes to override those methods.

ken2k
  • 48,145
  • 10
  • 116
  • 176
0

if I'm getting what you're saying I think what you're searching for is a base class with inheritance:

public class BaseClass // or abstract
{
    public void foo(int x)
    {
        //your implementation
    }
}

public class ChildClass : BaseClass
{
    public void foo(int x) : base(x)
    {
        //your implementation
    }
}
Danahi
  • 98
  • 1
  • 11
0

Use virtual and override.

class Program
{
    static void Main(string[] args)
    {
        MyBaseClass ext1 = new Ext1();
        ext1.DoSomething();

        MyBaseClass ext2 = new Ext2();
        ext2.DoSomething();

        Console.ReadKey(true);
    }
}

class MyBaseClass
{
    public void DoSomething()
    {
        DoSomethingBase();
    }

    protected virtual void DoSomethingBase()
    {
        Console.WriteLine("DoSomethingBase");
    }
}

class Ext1 : MyBaseClass
{

}

class Ext2 : MyBaseClass
{
    protected override void DoSomethingBase()
    {
        Console.WriteLine("Overridden DoSomethingBase");
    }
}

The Ext1 class does not override the base's behaviour, so DoSomethingBase() from the base class is used. Ext2 does override the base method, so the overridden method gets called. This code prints:

DoSomethingBase
Overridden DoSomethingBase

The MyBaseClass class can also be marked as abstract to prevent instantiation of the base class itself.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272