【问题标题】:How to construct a call to a method using dynamic如何使用动态构造对方法的调用
【发布时间】:2014-07-28 02:17:15
【问题描述】:

您好,我有一个包含很多类的命名空间,它们都有一个方法 Destroy(int id) 我想用动态词来调用那个方法。

这是我的例子:

public bool DeleteElement<T>(T tElement)
{
    Type t = typeof(T);

    dynamic element = tElement;
    var id = element.Id;

    //until here everything is fine
    //here I want to say 
    (namespace).myClassName.Destroy(id);
    //the name of  myClassName is like t.ToString()
}

我可以避免命名空间,包括顶部的 using。这个想法是使用动态而不是反射来调用该静态方法,请注意Destroy是T的静态方法。我需要这样的T.Destroy(id)

【问题讨论】:

  • 实际上针对的是哪个框架? dynamic 在 C# 3.0 中不可用。听起来是接口的好时机......(以及相关的泛型类型约束)
  • 我在 C# 3.0 中向人们提出了这个问题,因为有人可能知道这一点
  • 好的,但是它改变了我们可以使用的东西。我们仍然需要知道允许哪些框架元素。
  • @Zinov,关注c#-3.0 标签的人通常也会关注c# 标签,所以你不需要包含所有版本;)

标签: c# c#-4.0 dynamictype


【解决方案1】:

如果Destroy(int id) 是静态方法,你不能创建一个实例方法来调用静态方法吗?

public void Destroy()
{
    ThisClass.Destroy(this.Id);
}

然后您可以定义一个由所有这些类实现的IDestroyable 接口:

interface IDestroyable { void Destroy(); }

然后修改你的DeleteElement方法如下:

public bool DeleteElement<T>(T tElement) where T : IDestroyable
{
    tElement.Destroy();
}

这里不需要使用dynamic...实际上,在这种情况下使用dynamic 通常表明设计不佳。实际上需要 dynamic 是非常罕见的,除非在创建它的场景中(例如与动态语言的互操作)

(如果类已生成但它们具有partial 修饰符,则可以在生成器未触及的另一个文件中声明新方法)


编辑:如果生成的类不是partial,则不能修改它们...所以另一种解决方案是使用反射;我知道您想避免这种情况(出于性能原因,我假设),但是您可以通过对每种类型仅执行一次反射来限制性能影响:您只需要为每种类型创建和缓存一个委托。

class DestroyHelper<T>
{
    static readonly Action<int> _destroy;
    static readonly Func<T, int> _getId;
    static DestroyHelper()
    {
        var destroyMethod = typeof(T).GetMethod("Destroy", BindingFlags.Static | BindingFlags.Public);
        _destroy = (Action<int>)Delegate.CreateDelegate(typeof(Action<int>), destroyMethod);
        var getIdMethod = typeof(T).GetProperty("Id").GetGetMethod();
        _getId = (Func<T, int>)Delegate.CreateDelegate(typeof(Func<T, int>), getIdMethod);
    }

    public static void Destroy(T element)
    {
        _destroy(_getId(element));
    }
}

【讨论】:

  • 没有生成所有类,每次发生更改时,我都需要修复所有代码,将继承设置为 IDestroyable,这不是我正在寻找的方法
  • @Zinov,我假设您无法控制这些类的生成?他们是否偶然被宣布为partial?如果是,我的解决方案仍然可以工作。
  • @Zinov,我不建议使用反射(在我的原始答案中)。我认为不可能用dynamic 调用静态方法;我编辑了我的答案以提供一个使用反射但限制性能影响的解决方案。
  • 关于反射:你认为dynamic 是如何工作的?当处理本质上不是动态的对象时,它使用反射,因为它是访问静态未知成员的唯一方法。当然,它以非常优化的方式使用缓存等,但它必须使用反射。如果您认为使用 dynamic 可以使您的代码比使用反射更高效,请再想一想 ;)
  • @Zinov,我很确定用动态方法是不可能的。接口方法可能是最好的,因为它只使用静态类型系统,不涉及反射。
猜你喜欢
  • 2018-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 2013-01-02
相关资源
最近更新 更多