有没有一种方法可以让Action从Delegate接受任何Type作为唯一参数?

时间:2019-03-25 16:34:46

标签: c# generics reflection casting delegates

我从只知道一个参数的方法创建了一个it('navigate to D365', () => { cy.visit('https://wipropoc.crm8.dynamics.com') } ) ,后来又使用Delegate对其进行了调用,但是我想知道是否有可能获得DynamicInvoke来调用直接。

这是我目前拥有的:

Action

使用动作not only would it be faster but it would look much neater。以下代码不起作用,但是必须有一种方法可以得到类似的结果:

private IEnumerable<MethodInfo> GetMethods()
            => GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

private IEnumerable<Thing> GetThings() {
    foreach (var method in GetMethods()) {
        var attribute = (MyAttribute) method.GetCustomAttribute(typeof(MyAttribute), false);
        var theDelegate = CreateDelegate(method);

        return new Thing(attribute.Name, theDelegate);
    }
}

private Delegate CreateDelegate(MethodInfo method) {
    Type requestType = method.GetParameters()[0].ParameterType,
         actionType = typeof(Action<>).MakeGenericType(requestType);

    return Delegate.CreateDelegate(actionType, this, method);
}

public void Invoke(Thing thing, string json) {
    var requestType = MyDelegate.Method.GetParameters()[0].ParameterType;
    var o = Deserialize(json, requestType);

    thing.TheDelegate.DynamicInvoke(o);
}

3 个答案:

答案 0 :(得分:0)

由于Action<T>并非源自Action,因此无法将Action<T>分配给Action。但是两者都源自Delegate,因此您可以将它们分配给Delegate

我担心您将不得不坚持使用Delegate作为返回类型。

答案 1 :(得分:0)

如果您查看reference source,则会看到以下几行:

public delegate void Action<in T>(T obj); 
public delegate void Action(); 

ActionAction<T> 的代表,所以我不知道为什么这样做应该更快。

但更重要的是:您的代码无法使用,因为Action根本不是Action<T>,它没有参数。它们都是从Delegate派生的,而不是彼此派生的。

答案 2 :(得分:0)

由于我们不确切知道您的CreateDelegate方法从何处获取MethodInfo,因此我假设您可以直接访问适当的方法。因此,使用以下类,我们可以缓存由json string调用的委托。

public sealed class JsonInvoker<T>
{
    private readonly Action<T> _action;

    public JsonInvoker(Action<T> action)
    {
        _action = action;
    }

    public void Invoke(string json)
    {
        var arg = Deserialize(json);
        _action(arg);
    }

    private T Deserialize(string json) => //...
}

然后设置您的支持课程。

private readonly JsonInvoker<DataClass> _dataClassInvoker = 
    new JsonInvoker<DataClass>(DataClass.Process); // Pass the relevant method