[英]C# Delegate Type As Generic Constraint
I have a function:我有一个功能:
private void SetupCallbacks()
{
Type actionType = Type.GetType(CardData.ActionFile);
if (actionType == null)
return;
// To get any particular method from actionType, I have to do the following
MethodInfo turnStarted = actionType.GetMethod(CardData.TurnStartedMethod);
if (turnStarted != null)
{
Delegate d = Delegate.CreateDelegate(typeof(Action<bool>), turnStarted);
Action<bool> turnStartedAction = (Action<bool>)d;
TurnManager.Instance.OnTurnStarted += turnStartedAction;
}
...
}
actionType
is a class that contains several static methods. actionType
是一个包含多个静态方法的类。 These methods are stored as strings in the CardData object.这些方法作为字符串存储在 CardData 对象中。 I provided an example using the
OnTurnStarted
callback.我提供了一个使用
OnTurnStarted
回调的示例。 It is very clunky to write out all that code repeatedly each time I want to add another callback.每次我想添加另一个回调时,重复写出所有代码是非常笨拙的。 I've tried creating a function:
我试过创建一个函数:
private void SetupCallback<TDelegate>(Type actionType, string method, TDelegate delagateToAddThisTo) where TDelegate : Delegate
{
MethodInfo methodInfo = actionsContainerClass.GetMethod(method);
if (methodInfo != null)
{
Delegate d = Delegate.CreateDelegate(typeof(Action<Card>), methodInfo);
TDelegate t = (TDelegate)d;
delagateToAddThisTo += t;
}
}
However, where TDelegate : Delegate
doesn't work.但是,
where TDelegate : Delegate
不起作用。 I can't just do some type checking in the method (ie:我不能只在方法中做一些类型检查(即:
if(typeof(TDelegate).IsSubclassOf(typeof(Delegate)) == false)
{
throw new InvalidOperationException("Card::SetupCallback - " + typeof(TDelegate).Name + " is not a delegate");
}
because delagateToAddThisTo
which is of type TDelegate and needs to be able to be added to.因为
delagateToAddThisTo
类型并且需要能够添加到。
Thank you in advance.先感谢您。
C# doesn't allow constraining generic type parameters with delegate types. C# 不允许使用委托类型约束泛型类型参数。 Your only option to validate delegate types is at runtime.
验证委托类型的唯一选择是在运行时。
For the same reason, you won't be able to use the +=
operator inside the CreateCallback
method.出于同样的原因,您将无法在
CreateCallback
方法中使用+=
运算符。 But if +=
is moved to the caller ( SetupCallbacks
), and the CreateCallback
only creates and returns the delegate, it can still look quite elegant:但是如果
+=
被移动到调用者( SetupCallbacks
),并且CreateCallback
只创建和返回委托,它仍然看起来很优雅:
// this code is in SetupCallbacks method
// Action<...> delegates are just examples
TurnManager.Instance.OnTurnStarted +=
CreateCallback<Action<string, int>>(actionType, CardData.TurnStartedMethod);
TurnManager.Instance.OnTurnStopped +=
CreateCallback<Action<string, int, TimeSpan>>(actionType, CardData.TurnStoppedMethod);
Where the CreateCallback
method is as follows:其中
CreateCallback
方法如下:
private TDelegate CreateCallback<TDelegate>(Type actionType, string method)
where TDelegate : class
{
if (!typeof(Delegate).IsAssignableFrom(typeof(TDelegate)))
{
throw new InvalidOperationException("Card::SetupCallback - " + typeof(TDelegate).Name + " is not a delegate");
}
MethodInfo methodInfo = actionType.GetMethod(method);
if (methodInfo != null)
{
// the following line will also validate compatibility of delegate types
Delegate nonTypedDelegate = methodInfo.CreateDelegate(typeof(TDelegate));
TDelegate typedDelegate = (TDelegate)(object)nonTypedDelegate;
return typedDelegate;
}
return null;
}
Provided that in my example, TurnManager class looks like this:假设在我的示例中,TurnManager 类如下所示:
public class TurnManager
{
public static TurnManager Instance
{
get { /* ....... */ }
}
public Action<string, int> OnTurnStarted { get; set; }
public Action<string, int, TimeSpan> OnTurnStopped { get; set; }
//... other members ...
}
Starting from C# 7.3 it is possible.从 C# 7.3 开始是可能的。
Example from Microsoft docs Microsoft 文档中的示例
public class UsingEnum<T> where T : System.Enum { }
public class UsingDelegate<T> where T : System.Delegate { }
public class Multicaster<T> where T : System.MulticastDelegate { }
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.