Daniel Grandis Daniel Grandis - 28 days ago 19
C# Question

Attach Generic method event handler with unknow type

I need to attach this handler to a RadListView Column creation, by adding a DataSource to the control.

public void GenericColumnCreatingHandler<T>(object sender, ListViewColumnCreatingEventArgs e)
{
e.Column.Visible = BaseEntity<int>.MemberVisibility<T>
(e.Column.FieldName, TelerikPropertyVisibilityAttribute.VisibilityTypeEnum.BaseDetails);

e.Column.HeaderText = CaricaTestoLocale(e.Column.HeaderText, "Col_" + e.Column.HeaderText);

e.Column.BestFit();
e.Column.AutoSizeMode = ListViewBestFitColumnMode.AllCells;
}


My problem is that I need to perform the handler attach from this other generic method:

private void PopulateRecord(TipoTabellaBase tipo)
{
Type generic = typeof(CommonTableService<>);
Type[] typeArgs = { tipo.Tipo };
var constructed = generic.MakeGenericType(typeArgs);

var instance = Activator.CreateInstance(constructed);
if (instance == null)
return;

MethodInfo getEntities = constructed.GetMethod("GetEntitiesWithNoParameters");
//getEntities = getEntities.MakeGenericMethod(typeArgs);

var result = (IEnumerable<BaseEntity<int>>)getEntities.Invoke(instance, null);
lvRecords.ColumnCreating += base.GenericColumnCreatingHandler<BaseEntity<int>>;
lvRecords.DataSource = result;
BestFit(lvRecords);

generic = null;
typeArgs = null;
constructed = null;
getEntities = null;
instance = null;
}


The problematic row is this one:

lvRecords.ColumnCreating += base.GenericColumnCreatingHandler<BaseEntity<int>>


because BaseEntity is EF base type for all Entities, but this is not enought for the BaseEntity.MemberVisibility method; this method need to know the exact entity type to set the visible properties (and, of course, grid column) based on specific custom attribute on that.

Question is: how I can call base.GenericColumnCreatingHandler where T is TipoTabellaBase tipo.Tipo (type) without knowing type at design time?

Any help would be very appreciated!
Thanks is advance.

Daniel

Answer

Please note that this solution is untested.

You will have to instantiate the strongly-typed version of base.GenericColumnCreatingHandler<T> at runtime.

From your code, I figure you already know how to obtain a MethodInfo instance for a given method. You will need to get the MethodInfo for base.GenericColumnCreatingHandler<T> (let's call it genericMethodInfo).

Then, you can create a strongly-typed version of that method with MakeGenericMethod:

MethodInfo typedMethodInfo = genericMethodInfo.MakeGenericMethod(new[] {
                                 typeof(BaseEntity<int>)
                             });

Once that is done, you need to invoke CreateDelegate to obtain something that you can assign to the ColumnCreating event, as described here or here:

lvRecords.ColumnCreating +=
    (ListViewColumnCreatingEventHandler)typedMethodInfo.CreateDelegate(
        typeof(ListViewColumnCreatingEventHandler), this);

EDIT: Replaced base with this in the last code sample. In case an inherited method is specifically required, this has to be taken care of while retrieving genericMethodInfo.