C # Reflection Программные обработчики событий с пользовательскими аргументами событий - PullRequest
3 голосов
/ 18 января 2011

Вот моя проблема / сценарий

public class TestEventArgs : EventArgs
{
   public int ID { get; set; }
   public string Name { get; set; }
}

public event EventHandler<TestEventArgs> TestClick

Как я могу прикрепить EventHandler к TestClick с помощью отражения? (объект является экземпляром Activator.CreateInstance)

EventInfo eventClick = obj.GetType().GetEvent("TestClick");
Delegate handler = Delegate.CreateDelegate(eventClick.EventHandlerType, obj, ????);
eventClick.AddEventHandler(obj, handler);

Моя проблема в том, что TestEventArgs объявлен во внешней DLL, но ???? Для methodinfo выше требуется подпись в своем делегате?

Ответы [ 3 ]

7 голосов
/ 21 января 2011

Мне удается заставить мой код работать, следуя методике, описанной в следующей статье, http://www.pelennorfields.com/matt/2009/03/13/createdelegate-error-binding-to-target-method/

По сути, если я делаю следующее, я получаю ошибку "Ошибка привязки к целевому методу"",

FAIL:

EventInfo eventClick = obj.GetType().GetEvent("TestClick");
Delegate handler = Delegate.CreateDelegate(
    eventClick.EventHandlerType, this, "TestClick");
eventClick.AddEventHandler(obj, handler);

УСПЕХ:

Но когда я изменил его на:

MethodInfo methodOn_TestClick = this.GetType().GetMethod("TestClick", new Type[] { typeof(object), typeof(EventArgs));

Delegate handler = Delegate.CreateDelegate(
    event_DomClick.EventHandlerType, this, methodOn_TestClick, true); // note the change here

eventClick.AddEventHandler(obj, handler);

Затем я использовал отражение в своем методе TestClick, чтобы получить нужные мне свойства из стандартных EventArgs.

например.

public void TestClick(object sender, EventArgs e)
{
    PropertyInfo prop_ID = e.GetType().GetProperty("ID");

    int id = Convert.toInt32(prop_ID.GetValue(e, null));
}
1 голос
/ 18 января 2011

Контролируете ли вы источник целевой сборки? Если это так, просто добавьте атрибут сборки InternalsVisibleTo к целевой сборке.

0 голосов
/ 18 января 2011

Если вы использовали Activator.CreateInstance(), у вас есть ссылка на тип вашего объекта, верно?

Чтобы добавить свой собственный обработчик:

Вызов type.GetFields() теперь у вас есть внутренние поля (если событие определено в базовом классе, вам нужно сначала пройти вверх по иерархии, используя type.BaseType, чтобы подняться на уровень, чтобы вы достигли нужного уровня).

Как только у вас есть экземпляр FieldInfo для делегата, поддерживающего вызов обработчика события GetValue() для экземпляра FieldInfo, передающего ваш объект. Теперь у вас есть делегат, поддерживающий обработчик события.Теперь позвоните FieldInfo.SetValue(myObject, Delegate.Combine(currentValue, myHandler)).

Я уверен, что с Delegate.Combine вам просто нужно убедиться, что подпись вашего обработчика событий совпадает, а не фактический тип.Поэтому этого должно быть достаточно для создания собственного делегата с такой же подписью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...