2

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

1 Answers1

1

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.

Community
  • 1
  • 1
O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114
  • Hi O. R. Mapper, thank for your suggestion. All seem good, except the base keyword on the last call. This is the new code: MethodInfo genericColCreating = base.GetType().GetMethod("GenericColumnCreatingHandler"); MethodInfo typedColCreaeting = genericColCreating.MakeGenericMethod(new [] { typeArgs[0] }); lvRecords.ColumnCreating += (ListViewColumnCreatingEventHandler)typedColCreaeting.CreateDelegate( typeof(ListViewColumnCreatingEventHandler), base); compiler says that using base keyword in this context is not valid... – Daniel Grandis Nov 10 '16 at 10:28
  • Thanks O.R. Mapper, I've switched base keyword with this and all working good! You save my day! Just another question about stackoverflow: why I can't give a +1 to your response? I've no reputation but I don't know how to achieve it!!! – Daniel Grandis Nov 10 '16 at 10:38
  • @DanielGrandis: Oh, sorry, didn't consider the case that `base` on its own cannot be used like that. But with that said, you may have to take care to find the right `MethodInfo` initially, given that you intentionally fetch the inherited version (by using `base`) rather than an overridden one in the current class. If that's not actually the case (and you could just as well have written `this.GenericColumnCreatingHandler`, nothing special has to be considered, of course. – O. R. Mapper Nov 10 '16 at 10:43
  • @DanielGrandis: According to [this list of priviledges](http://stackoverflow.com/help/privileges), you need a reputation of 15 or more to upvote. You can gather more reputation by writing good questions and answer - each upvote to one of your questions will increase your rep by 5, and each upvote to one of your answers will increase your rep by 10. As for my answer, if this answer helped you, you can *accept* it (by clicking the checkmark right below the voting buttons). Accepting an answer will also increase your reputation by 2, so you will soon reach 15 reputation points. – O. R. Mapper Nov 10 '16 at 10:45
  • Perfect! I've gained 15 reputation just now! So, first of all, I've place a +1 to your usefull answer to my question! Thanks a lot! – Daniel Grandis Nov 10 '16 at 11:19