Pass delegate/event as ref generic parameter


Sergio Romero

We are dealing with a lot of legacy WinForms code and are slowly refactoring, breaking down dependencies, implementing the MVP pattern and moving logic from forms and user controls into the presenter.

We've added Castle Windsor, which creates a ViewFactory that returns a form/user control with the Presenter and all its dependencies attached.

A user control is used on almost every screen and we have refactored it but haven't finished refactoring all the screens that use it, so some of them are using the ViewFactory and some are still calling the control's constructor , but of course doesn't create a presenter.

Although what I can fix is ​​to check if the events the control has now are null, if so it means no presenter has subscribed to them, so I create it manually. This works, but since there are some events that can fire at different times, it means I have to do the following:

private void RaiseEventForPresenter(ref EventHandler action, EventArgs e)
{
   if(action == null) CreatePresenter();

   action.Invoke(this, e);
}

private void RaiseEventForPresenter(ref CustomDelegate1 action, CustomDelegate1EventArgs e)
{
   if(action == null) CreatePresenter();

   action.Invoke(this, e);
}

private void RaiseEventForPresenter(ref CustomDelegate2 action, CustomeDelegate2EventArgs e)
{
   if(action == null) CreatePresenter();

   action.cInvoke(this, e);
}

private void CreatePresenter()
{
    new Presenter(this, new Bl(new Dal(new ConnectionManager())));
}

Note that the delegate needs to be passed as a ref in order for it to be successfully called after the presenter is created and subscribed to view events.

Instead of using a different overloaded method for each event, I want to do this:

private void RaiseEventForPresenter<T1, T2>(ref T1 action, T2 e)
{
    if (action == null) CreatePresenter();

    action.Invoke(this, e); //Does not compile
}

Of course, T1 does not contain the definition of the Invoke method . So far I have tried:

Convert action to action:

((Action<object, T2)action).Invoke(this, e);

Redefine T1 to represent:

private void RaiseEventForPresenter<T>(ref Delegate action, T e) ...

Redefine T1 as an action:

private void RaiseEventForPresenter<T>(ref Action<object, T> action, T e) ...

All these options give me different compile errors, so my question is, can this be done?

Wu

This problem is hard to solve because generics do not allow delegates as type constraints , so we cannot write generic methods that will accept any specific type of delegate.

But we can specify type constraints on the type parameters in the delegate . So the solution is to get rid CustomDelegate1of and CustomDelegate2and instead use a generic version of such as , CustomDelegate<T>and pass the event arg type as a generic parameter.

Here's what the delegate and event parameter definitions look like:

public class CustomEventArgs1 : EventArgs { }


public class CustomEventArgs2 : EventArgs { }

public delegate void CustomDelegate<T>(object sender, T e) where T : EventArgs;

Here is your method:

public void RaiseEventForPresenter<T>(ref CustomDelegate<T> action, T args) where T : EventArgs
{
    if (action == null) CreatePresenter();
    action(this, args);
}

Related


Pass delegate/event as ref generic parameter

Sergio Romero We are dealing with a lot of legacy WinForms code and are slowly refactoring, breaking down dependencies, implementing the MVP pattern and moving logic from forms and user controls into the presenter. We've added Castle Windsor, which creates a V

Pass generic parameter to method

User 11383582 I have a small question about generic programming in Java. Is there a way to check the type of the parameter passed to the method? I want to compare the type of the instance on which the method is called and the arguments passed to it. If they ar

Pass generic function as parameter

dpzmick I want to be able to pass a generic function to another function (in this case a closure) without losing the "genericity" of the passed function. Since this is a convoluted statement, here is an example: use std::fmt::Debug; fn test<F, I: Debug>(gen:

Pass generic parameter to method

User 11383582 I have a small question about generic programming in Java. Is there a way to check the type of the parameter passed to the method? I want to compare the type of the instance on which the method is called and the arguments passed to it. If they ar

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass parameter to $ref in OpenAPI 3

some development Suppose I have the following schema for later use $ref: "schemas": { "Order": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "petI

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass parameter to $ref in OpenAPI 3

some development Suppose I have the following schema for later use $ref: "schemas": { "Order": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "petI

Python pass ref int as parameter

Mr. Sha The tlb library in my python project passes win32com.client. I've easily used a number of built-in functions, but one of the main functions takes a list of arguments for two of them marked as ref int. When I try to pass a python integer to the function

Pass class with generic parameter to annotation

Miffett: I wonder why the Java compiler doesn't accept this assignment: Class<? extends List<?>> blbost = ArrayList.class; Note that I'm not interested in solutions like this Class<? extends List<?>> blobst = (Class<? extends List<?>>)ArrayList.class;, I'd li

Kotlin pass KType as generic parameter

LambdaBeta I have a situation where I want to call a function to produce an object that I only have the type described by KType. Basically I have: inline fun<reified T> coolFunction(from : String) : T = // Okay, I'll be honest - its a JSON parser ... fun myOth

Pass generic parameter object in stream

Elias I can pass the type as a generic parameter, but when I use an object that contains typed parameters, Flow doesn't understand nor suggest the type. Instead, I get an error. export type TAction<T, R> = { +type: string, payload?: T, meta?: R }; function th

Pass class as parameter to generic function

flexographic printing I'm using this neat class to map datatables into objects in a MySQL database. Now, I want to write a generic function that returns a list of various different classes so that I can call: List<Person> persons = ReadDataTable<Person>(); Lis

Kotlin pass KType as generic parameter

LambdaBeta I have a situation where I want to call a function to produce an object that I only have the type described by KType. Basically I have: inline fun<reified T> coolFunction(from : String) : T = // Okay, I'll be honest - its a JSON parser ... fun myOth

Pass object as parameter to generic object

hi mark I want to pass object with method setName to generic type of object. one example: //Instead of obj.setName = "John"; do this: aMethod(obj); aMethod(different_obj); //different_obj has also a method setName public aMethod(object anOtherObj) { anOther

Pass object as parameter to generic object

hi mark I want to pass object with method setName to generic type of object. one example: //Instead of obj.setName = "John"; do this: aMethod(obj); aMethod(different_obj); //different_obj has also a method setName public aMethod(object anOtherObj) { anOther

Pass class with generic parameter to annotation

Miffett: I wonder why the Java compiler doesn't accept this assignment: Class<? extends List<?>> blbost = ArrayList.class; Note that I'm not interested in solutions like this Class<? extends List<?>> blobst = (Class<? extends List<?>>)ArrayList.class;, I'd li

Kotlin pass KType as generic parameter

LambdaBeta I have a situation where I want to call a function to produce an object that I only have the type described by KType. Basically I have: inline fun<reified T> coolFunction(from : String) : T = // Okay, I'll be honest - its a JSON parser ... fun myOth

Pass generic parameter object in stream

Elias I can pass the type as a generic parameter, but when I use an object that contains typed parameters, Flow doesn't understand nor suggest the type. Instead, I get an error. export type TAction<T, R> = { +type: string, payload?: T, meta?: R }; function th

Pass class as parameter to generic function

flexographic printing I'm using this neat class to map datatables into objects in a MySQL database. Now, I want to write a generic function that returns a list of various different classes so that I can call: List<Person> persons = ReadDataTable<Person>(); Lis

Kotlin pass KType as generic parameter

LambdaBeta I have a situation where I want to call a function to produce an object that I only have the type described by KType. Basically I have: inline fun<reified T> coolFunction(from : String) : T = // Okay, I'll be honest - its a JSON parser ... fun myOth

Kotlin pass KType as generic parameter

LambdaBeta I have a situation where I want to call a function to produce an object that I only have the type described by KType. Basically I have: inline fun<reified T> coolFunction(from : String) : T = // Okay, I'll be honest - its a JSON parser ... fun myOth

Pass generic parameter object in stream

Elias I can pass the type as a generic parameter, but when I use an object that contains typed parameters, Flow doesn't understand nor suggest the type. Instead, I get an error. export type TAction<T, R> = { +type: string, payload?: T, meta?: R }; function th

Pass object as parameter to generic object

hi mark I want to pass object with method setName to generic type of object. one example: //Instead of obj.setName = "John"; do this: aMethod(obj); aMethod(different_obj); //different_obj has also a method setName public aMethod(object anOtherObj) { anOther

Pass generic parameter object in stream

Elias I can pass the type as a generic parameter, but when I use an object that contains typed parameters, Flow doesn't understand nor suggest the type. Instead, I get an error. export type TAction<T, R> = { +type: string, payload?: T, meta?: R }; function th

How to pass a generic class as a generic parameter of a method

Jaroslaw K. I have a problem with passing a class as a generic parameter of a method, if I have a simple method: <T> T sendRequest(SomeRestApiRequest request, Class<T> responseClass) Parses the response to the specified form. I use them this way: ItemListJSON