Unity fails to create an object with EventHandler<>

Jun 12, 2008 at 7:47 AM

hello, I just encountered one problem. When a class have the following statement, Unity fails to instantiate an object. 
...
public event EventHandler<ItemAddedEventArgs> ItemAdded;
...

 However, it does create an instance if I change the proceeding statement to 
...
public event EventHandler ItemAdded;
...

Is it a bug in Unity?

Jun 12, 2008 at 7:25 PM
Could you post a small, complete sample that demonstrates the problem?

Jun 13, 2008 at 8:53 AM
oops, I made a mistake. Unity can create the object. But the SimpleEventBrokerExtension can't. Here's the code. These code fails. But if you make the change as I mentioned in the previous post, it works. I guess
Transaction.cs

using System;
using System.Collections.Generic;
using System.Linq;
using EventBrokerExtension;
using Microsoft.Practices.Unity;

namespace Test
{
    public class Transaction
    {
        public int TransactionNumber
        {
            get { return 100;}
        }

        //Using an attribute register an event in the EventBroker
        [Publishes("ItemAddedEvent")]
        public event EventHandler<ItemAddedEventArgs> ItemAdded;

        public void FireEvent(string itemCode)
        {
            OnItemAdded(this, new ItemAddedEventArgs(itemCode));
        }

        //Method you will call to trigger the event in the EventBroker
        private void OnItemAdded(object sender, ItemAddedEventArgs ea)
        {
            EventHandler<ItemAddedEventArgs> handlers = ItemAdded;
            if (handlers != null)
            {
                handlers(sender, ea);
            }
        }
    }

    public class ItemAddedEventSubscriber
    {
        [SubscribesTo("ItemAddedEvent")]
        public void OnItemAddedEventFired(object sender, ItemAddedEventArgs e)
        {
            MessageBox.Show("ItemAddedEventSubscriber1 catch the event");
        }
    }

    public class ItemAddedEventArgs : EventArgs
    {
        private string _itemCode;

        public ItemAddedEventArgs(string itemCode)
        {
            _itemCode = itemCode;
        }

        public string AddedItemCode
        {
            get { return _itemCode; }
        }
    }

    class Tester
    {
        private Transaction _transaction;
        [Dependency]
        public Transaction Transaction
        {
            get { return _transaction; }
            set { _transaction = value; }
        }

        private ItemAddedEventSubscriber _sub1;
        [Dependency]
        public ItemAddedEventSubscriber Subscriber
        {
            get { return _sub1; }
            set { _sub1 = value; }
        }

        public void Fire()
        {
            Transaction.FireEvent("100");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Create parent container
            IUnityContainer mainContainer = new UnityContainer();
            mainContainer.AddNewExtension<SimpleEventBrokerExtension>();

            Tester tester = (Tester)mainContainer.Resolve(typeof(Tester));

            tester.Fire();

        }
    }
}

Dec 4, 2009 at 5:15 PM
Edited Dec 4, 2009 at 5:17 PM

I have the same issue.

If my event use EventHandler it works but if I user any kind of EventHandler<TEventArgs> it doenst.

But I still didn't found a solution. Anyone knows how can I change the SimpleEventBroker class to allow other EventHandlers signature?

Thanks.

Apr 9, 2010 at 3:44 PM

Hi,

I also needed to handle custom events (with custom event arguments) through Unity EventBroker. We should not refer concrete event argument types (defined elsewhere) from SimpleEventBroker as that would break the "Loose Coupling" objective of the event broker. I did this simple thing which would serve my purpose, check if helps you.

Step 1:
Add the following code was added in a class called GlobalEventArgs.cs in the SimpleEventBroker project (supplied with Unity 1.2 Quick Starts)

using System;
using System.Collections.Generic;
using System.Text;

namespace SimpleEventBroker
{
    public class GlobalEventArgs : EventArgs
    {
        object _eventData;

        public GlobalEventArgs(object eventData)
        {
            _eventData = eventData;
        }

        public object EventData
        {
            get { return _eventData; }
        }

        public override string ToString()
        {
            return _eventData.ToString();
        }

    }
}

Step 2:
Change the following everywhere in the EventBrokerExtension and SimpleEventBroker projects.

Find:    EventHandler
Replace with:   EventHandler<GlobalEventArgs>

If you are using the two UnitTest projects supplied with EventBroker then make changes in those projects too.

Step 3:
Declare events in your sources (event publishers) as below -

public event EventHandler<GlobalEventArgs> someEventName;

Step 4:
Declare event handler in your subscriber as below, so that it can receive the GlobalEventArgs argument.

SomeEventHandler(object sender, GlobalEventArgs e)

Step 5:
Register your event publisher and subscribers usually, either through publish/subscribe attributes (refer EventBroker help)  or by calling RegisterPublisher / RegisterSubscriber methods of the SimpleEventBroker.EventBroker() class. If you are using the RegisterPublisher / RegisterSubscriber methods then you have to create an instance of SimpleEventBroker.EventBroker() class somewhere so that both your subscribers and publishers get access to the same instance of that class. You can use a singleton for this purpose. For testing, I created the instance in Program.cs, i.e. in the main program, and passed the instance to both my publisher and subscriber forms through constructors. See how I am passing the instance to the first form. I am creating the second form from Load() event of  first form and passing the same broker instance that was received to the second form constructor.

Creating and passing EventBroker to first form:

             // Create the event broker
            SimpleEventBroker.EventBroker eventBroker = new SimpleEventBroker.EventBroker();

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1(eventBroker));

Passing same EventBroker to second form:

             // Create and show form2
            frm2 = new Form2(broker);
            frm2.Show();

Step 6:
Raise the event as below from the publisher.

FilterChanged(this, new GlobalEventArgs(someDataAsObject));

Step 7:
Handle the event from the subscriber. Note that any data that you have sent from the publisher as  Object() is now available in your subscriber. However, you may need to downcast the same to start working with it. But I think that is acceptable. I am sending my complete business object wrapped in Object() from the publisher and receiving the complete business object in the subscriber. Pretty simple way to use EventBroker without the wonderful loose coupling benefits.

Hope it helps all of you. You can mail me at rajabasuroy@hotmail.com for any queries. I would love to try answering.

Rajarshi