Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在打开代理和关闭代理之间执行转换的方法_C#_Performance_Generics_Reflection_Delegates - Fatal编程技术网

C# 在打开代理和关闭代理之间执行转换的方法

C# 在打开代理和关闭代理之间执行转换的方法,c#,performance,generics,reflection,delegates,C#,Performance,Generics,Reflection,Delegates,我需要有效地将开放委托(其中未指定目标)转换为封闭委托。我已经分析了我的代码,使用CreateDelegate()为实例方法生成闭合委托的成本占总运行时间的很大一部分(>60%)(因为它发生在该类型的每个新实例上) 有关打开和关闭委托的一些基本信息,请参见CreateDelegate的文档 我目前的方法是找到一种缓存打开的委托的方法(因此生成委托的成本只发生一次),并使用另一种方法调用它,该方法向委托提供隐式的“this”参数 一个复杂的因素是,除了通过代码中的泛型参数之外,我不知道委托将在编译

我需要有效地将开放委托(其中未指定目标)转换为封闭委托。我已经分析了我的代码,使用
CreateDelegate()
为实例方法生成闭合委托的成本占总运行时间的很大一部分(>60%)(因为它发生在该类型的每个新实例上)

有关打开和关闭委托的一些基本信息,请参见
CreateDelegate
的文档

我目前的方法是找到一种缓存打开的委托的方法(因此生成委托的成本只发生一次),并使用另一种方法调用它,该方法向委托提供隐式的“this”参数

一个复杂的因素是,除了通过代码中的泛型参数之外,我不知道委托将在编译时表示的方法的签名。此外,我希望避免反射(例如,
Invoke()
DynamicInvoke()
),因为它们在性能方面没有任何改进

static TDel CreateOpenDelegate<TDel>( MethodInfo mi )
{
    // creates and returns an open delegate for a delegate of signature TDel
    // that will invoke some method as described by MethodInfo {mi}
    return (TDel)(object)Delegate.CreateDelegate( typeof(TDel), mi );
}

// simplification of some other code...
// Note that Action<T> is a sample usage, the actual delegate signature and
// invocation parameters vary, and are defined by the consumers of my code
private Action<T> myAction = CreateOpenDelegate<Action<U,T>>( someMethodInfo );
myAction( this, default(T) ); // can't do this since {this} is a hidden parameter...
静态TDel CreateOpenDelegate(MethodInfo mi)
{
//为签名为TDel的委托创建并返回打开的委托
//它将调用MethodInfo{mi}所描述的某个方法
return(TDel)(object)Delegate.CreateDelegate(typeof(TDel),mi);
}
//其他一些代码的简化。。。
//注意,Action是一个示例用法,实际的委托签名和
//调用参数各不相同,由代码的使用者定义
私有操作myAction=CreateOpenDelegate,不幸的是,因为我事先不知道代理签名,所以我看不到一种方法来适应这里描述的方法


任何帮助都将不胜感激。

您是否正在尝试将代理或
MethodInfo
转换为已关闭的代理

如果您试图将一个委托转换为一个封闭委托,那么像这样使用curry如何

static Action<T2> Curry<T1, T2>(Action<T1, T2> del, T1 obj) { return p => del(obj, p); }
static Action Curry(Action del,T1 obj){return p=>del(obj,p);}

如果我正确理解了您的需求,您可能可以使用表达式树来实现这一点-我有一篇文章探讨了这个主题*。以下是一个简化版本:

public static D GetMethodAccessor<D>(MethodInfo mi) where D : class
{
    Type[] args = typeof(D).GetGenericArguments();
    if (args.Length == 0)
        throw new ArgumentException("Type argument D must be generic.");

    Type instanceType = args[0];

    // If return type is not null, use one less arg
    bool isAction = mi.ReturnType == typeof(void);
    int callArgCount = args.Length - (isAction ? 1 : 2);
    Type[] argTypes = args.Skip(1).Take(callArgCount).ToArray();

    var param = Expression.Parameter(instanceType, "obj");
    var arguments = argTypes.Select((t, i) => Expression.Parameter(t, "p" + i))
                            .ToArray();
    var invoke = Expression.Call(param, mi, arguments);
    var lambda = Expression.Lambda<D>(invoke,
                     Enumerable.Repeat(param, 1).Concat(arguments));

    Debug.WriteLine(lambda.Body);
    return lambda.Compile();
}
publicstaticd GetMethodAccessor(MethodInfo-mi),其中D:class
{
Type[]args=typeof(D).GetGenericArguments();
如果(args.Length==0)
抛出新ArgumentException(“类型参数D必须是泛型的”);
类型instanceType=args[0];
//如果返回类型不为null,请少使用一个参数
bool isAction=mi.ReturnType==typeof(void);
int callArgCount=args.Length-(isAction?1:2);
Type[]argTypes=args.Skip(1).Take(callArgCount.ToArray();
var param=Expression.Parameter(instanceType,“obj”);
var arguments=argTypes.Select((t,i)=>Expression.Parameter(t,“p”+i))
.ToArray();
var invoke=Expression.Call(参数、mi、参数);
var lambda=Expression.lambda(调用,
可枚举.Repeat(参数,1).Concat(参数));
Debug.WriteLine(lambda.Body);
返回lambda.Compile();
}
尽管如此,我不确定额外的类型参数处理和表达式编译将如何与您的方法进行比较

就提供隐式“this”而言,可以使用扩展方法吗

private static Action<U,T> myAction = GetMethodAccessor<Action<U,T>>(myMethod);
public static void MyAction<U,T>(this U u, T t)
{
    myAction(u, t);
}
私有静态操作myAction=GetMethodAccessor(myMethod);
公共静态无效MyAction(此U,T)
{
myAction(u,t);
}

*请注意,我在文章中使用的基于字符串的字典缓存效率非常低-您可能希望将委托缓存到一个私有实例,如您的示例中所示。

不幸的是,我事先不知道方法签名,因此无法以这种方式显式缓存参数。操作可以是由代码使用者定义的任意委托。如果是,您希望转换为哪种委托类型?或者您会有两个通用参数>