【问题标题】:Attach Generic method event handler with unknow type附加未知类型的通用方法事件处理程序
【发布时间】:2017-03-24 07:20:51
【问题描述】:

我需要通过向控件添加 DataSource 来将此处理程序附加到 RadListView 列创建。

 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;
    } 

我的问题是我需要从其他通用方法执行处理程序附加:

  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;          
    }

有问题的行是这一行:

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

因为 BaseEntity 是所有实体的 EF 基类型,但这对于 BaseEntity.MemberVisibility 方法来说还不够;此方法需要知道确切的实体类型才能根据特定的自定义属性设置可见属性(当然还有网格列)。

问题是:我如何在设计时不知道类型的情况下调用 base.GenericColumnCreatingHandler 其中 T 是 TipoTabellaBase tipo.Tipo (type)?

任何帮助将不胜感激! 提前谢谢。

丹尼尔

【问题讨论】:

  • “来自其他泛型方法”-PopulateRecord 不是“泛型方法”(在 C# 意义上)。
  • 是的映射器,你是对的。但是,我认为,这还不是真正的问题......

标签: c# generics reflection


【解决方案1】:

请注意,此解决方案未经测试。

您必须在运行时实例化base.GenericColumnCreatingHandler&lt;T&gt; 的强类型版本。

从您的代码中,我想您已经知道如何为给定方法获取MethodInfo instance。您需要为base.GenericColumnCreatingHandler&lt;T&gt; 获取MethodInfo(我们称之为genericMethodInfo)。

然后,您可以使用MakeGenericMethod 创建该方法的强类型版本:

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

完成后,您需要调用CreateDelegate 以获取可以分配给ColumnCreating 事件的内容,如herehere 所述:

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

编辑:在最后一个代码示例中将 base 替换为 this。如果特别需要继承方法,则在检索 genericMethodInfo 时必须注意这一点。

【讨论】:

  • 您好 O. R. Mapper,感谢您的建议。一切似乎都很好,除了最后一次调用的 base 关键字。这是新代码: MethodInfo genericColCreating = base.GetType().GetMethod("GenericColumnCreatingHandler"); MethodInfo typedColCreaeting = genericColCreating.MakeGenericMethod(new [] { typeArgs[0] }); lvRecords.ColumnCreating += (ListViewColumnCreatingEventHandler)typedColCreaeting.CreateDelegate( typeof(ListViewColumnCreatingEventHandler), base);编译器说在这种情况下使用 base 关键字是无效的......
  • 谢谢 O.R.映射器,我已经用这个切换了基本关键字并且一切正常!你拯救了我的一天!关于stackoverflow的另一个问题:为什么我不能给你的回复+1?我没有名声,但我不知道如何实现它!!!
  • @DanielGrandis:哦,对不起,没有考虑到base 本身不能这样使用的情况。但是话虽如此,您最初可能必须小心找到正确的MethodInfo,因为您有意获取继承的版本(通过使用base)而不是当前类中的覆盖版本。如果实际情况并非如此(您也可以写this.GenericColumnCreatingHandler,当然,没有什么特别需要考虑的。
  • @DanielGrandis:根据this list of priviledges,您需要 15 或更多的声望才能投票。你可以通过写出好的问题和答案来获得更多的声誉——对你的一个问题的每一个赞都会增加你 5 的声望,对你的一个答案的每一个赞都会让你的声望增加 10。至于我的回答,如果这个答案有帮助你,你可以接受它(通过点击投票按钮正下方的复选标记)。接受答案也会使您的声望增加 2,因此您很快就会达到 15 点声望。
  • 完美!我刚刚获得了15点声望!所以,首先,我对你对我的问题的有用回答加了一个+1!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-24
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多