Question

So I was trying to create my own event for the initialization of a class called Car, which inherits from an Automobile object. Below is the same in C# code:

`

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Abc.Training.Artifacts;

namespace Abc.Training.Objects
{
    public abstract class Automobile
    {
        public string Model { get; set; }
        public string Manufacturer { get; set; }
        public string YoM { get; set; }
    }

    public class Car : Automobile 
    {
        public static event Delegates.ObjectInitHandler OnInit;

        public string MarketSegment { get; set; }
        public int BootSpace { get; set; } 

        public Car(string model, string manufacturer, string yom)
        {
            Model = model ;
            Manufacturer = manufacturer;
            YoM = yom;
            ObjectInitEventArgs eArgs = new ObjectInitEventArgs();
            eArgs.IsResidentObject = true;
            eArgs.ObjectType = this.GetType();
            if (OnInit != null) OnInit(this, eArgs);
        }

    }
}

`

The ObjectInitHandler and its args (the delegate type used here) is also created by me as:

`

public delegate void ObjectInitHandler(object sender, ObjectInitEventArgs e);
 public class ObjectInitEventArgs:EventArgs
    {
        public Type ObjectType { get; set; }
        public bool IsResidentObject { get; set; }
    }

`

I am subscribing to the event as below:

`

Car.OnInit += new Delegates.ObjectInitHandler(Car_OnInit);//able to do this as event is static
Car c = new Car("Maruti", "Maruti", "2004");
void Car_OnInit(object sender, ObjectInitEventArgs e)
{
   Console.WriteLine("Car object initialized");
}

`

I wanted to create an event OnInit for this class. However, if I put an instance event OnInit in the publisher (my Car class), I will have to initialize the class first before I can subscribe to this event. Since I would like to fire this event on initialization, this becomes a chicken and egg problem for me.

I solved it by creating a static event Object and doing the subscription before the object initialization as shown below (this is a snippet from the code above itself):

public static event Delegates.ObjectInitHandler OnInit;

However, in an ASP.NET application, this would mean if multiple users access this application, I will have the same delegate object that will have duplicate subscriptions of events (because its static), which is obviously not cool.

Is there a design pattern which I can follow to have the event also as an instance member but still I can subscribe to the event before instantiation?

Was it helpful?

Solution 2

here is a way to do it, it don't use statics, and i used Actions instead of event arguments. (you can use it your way!)
note that i passed the callback function to the object when creating!

class Program
{
    static void Main(string[] args)
    {
        Car c = new Car("Maruti", "Maruti", "2004", Car_OnInit);

        Console.WriteLine("Press a key to exit...");
        Console.ReadKey();
    }
    static void Car_OnInit()
    {
        Console.WriteLine("Car object initialized");
    }

}
public abstract class Automobile
{
    public string Model { get; set; }
    public string Manufacturer { get; set; }
    public string YoM { get; set; }
}

public class Car : Automobile
{
    public event Action OnInit;

    public string MarketSegment { get; set; }
    public int BootSpace { get; set; }

    public Car(string model, string manufacturer, string yom, Action callBack)
    {
        this.OnInit += callBack;
        Model = model;
        Manufacturer = manufacturer;
        YoM = yom;
        if (OnInit != null) OnInit();
    }

}

Also you can pass any argumenst if you want, just use Action<T> like Action<string> instead of Action. then your callback will be Car_OnInit(string)

OTHER TIPS

I think you have to pass that function as a callback:

public class Car : Automobile 
    {
      // public static event Delegates.ObjectInitHandler OnInit; remove this

        public string MarketSegment { get; set; }
        public int BootSpace { get; set; } 

        public Car(string model, string manufacturer, string yom,ObjectInitHandler OnInit) //add the callback as parameter.
        {
            Model = model ;
            Manufacturer = manufacturer;
            YoM = yom;
            ObjectInitEventArgs eArgs = new ObjectInitEventArgs();
            eArgs.IsResidentObject = true;
            eArgs.ObjectType = this.GetType();
            if (OnInit != null) OnInit(this, eArgs);
        }

    }

Pass a callback to the constructor when initializing an object:

Car c = new Car("Maruti", "Maruti", "2004",new Delegates.ObjectInitHandler(Car_OnInit));
void Car_OnInit(object sender, ObjectInitEventArgs e)
{
   Console.WriteLine("Car object initialized");
}

Actually, I don't see a need for an initialization event in your code unless there are asynchronous operations inside your constructor.

There is no need (even if it were possible). You have everything you need.

Firstly, you wouldn't subscribe to the event each page load/per user. You would do it once.. in Application_Start for example.

Second.. you have everything you need in the event. Notice this line of code:

if (OnInit != null) OnInit(this, eArgs);

You pass this as the sender argument. this is an instance of Car. So, in your event.. you have the instance you care about:

void Car_OnInit(object sender, ObjectInitEventArgs e) {
    var instance = sender as Car;

    // use instance here.
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top