您好我尝试将一个泛型强制转换为具有未知数量和类型的参数
的Action目前它看起来像:
public class subscriber
{
public subscriber()
{
new Subscription<Action>(a);
new Subscription<Action<string>>(b);
new Subscription<Action<int,string>>(c);
}
private void a() { }
private void b(string gg){}
private void c(int i, string g) { }
}
public class Subscription<T>
{
public T MyAction {get {retun _action;}}
public Type MyActionType {get;private set;}
public Subscription( T action )
{
MyAction = action;
MyActionType = action.GetType();
var gg = action.GetType().GetGenericArguments();// Contains the Sub generics
}
}
目前我们知道它将是一个动作,我们也知道子类型但是如何把它们放在一起
执行我的private void c(int i, string g)
方法
是在Action
移交某些参数时从Third-Class
(包含List<Subscription>
)执行Fourth-Class
答案 0 :(得分:4)
public abstract class SubscriptionBase
{
public abstract void ExecuteAction(params object[] parameters);
}
public class Subscription<T> : SubscriptionBase
{
private T _action;
public Subscription(T a)
{
_action = a;
}
public override void ExecuteAction(params object[] parameters)
{
(_action as Delegate).DynamicInvoke(parameters);
}
}
你可以像使用它一样使用它;
Action<int> func1 = (q) => q += 1;
Action<int, int> func2 = (q, w) => q += w;
Subscription<Action<int>> s1 = new Subscription<Action<int>>(func1);
Subscription<Action<int, int>> s2 = new Subscription<Action<int, int>>(func2);
List<SubscriptionBase> subscriptionBase = new List<SubscriptionBase>();
subscriptionBase.Add(s1);
subscriptionBase.Add(s2);
subscriptionBase[1].ExecuteAction(1, 2);
答案 1 :(得分:1)
你不能这样做。您无法将Subscription<Action<int>>
放入与Subscription<Action<string, Foo>>
相同的列表中。
我建议您创建一个如下所示的界面并将其存储在您的第三个类中:
interface IActionExecutor
{
bool CanExecuteForParameters(params object[] parameters);
void Execute(params object[] parameters);
}
// Implementation for one parameter
// You need to create one class per additional parameter.
// This is similar to the Action delegates in the framework.
// You can probably extract a base class here that implements
// some of the repetitive pars
public class ActionExecutor<in T> : IActionExecutor
{
private Action<T> _action;
public ActionExecutor(Action<T> action)
{
if(action == null) throw new ArgumentNullException("action");
_action = action;
}
public bool CanExecuteForParameters(params object[] parameters)
{
if(parameters == null) throw new ArgumentNullException("action");
if(parameters.Length != 1) return false;
return parameters[0] is T;
}
public void Execute(params object[] parameters)
{
if(parameters == null) throw new ArgumentNullException("action");
if(parameters.Length != 1)
throw new ArgumentOutOfRangeException("action");
_action((T)parameters[0]);
}
}
在第三节课中,您将获得IActionExecutor
s的列表:
List<IActionExecutor> _subscriptions;
你会像这样使用它:
public void Execute(params object[] parameters)
{
var matchingSubscriptions =
_subscriptions.Where(x => x.CanExecuteForParameters(parameters);
foreach(var subscription in matchingSubscriptions)
subscription.Execute(parameters);
}
为了简化ActionExecutor实例的创建,您可以提供工厂类:
public static class ActionExecutor
{
public IActionExecutor Create(Action action)
{
return new ActionExecutor(action);
}
public IActionExecutor Create<T>(Action<T> action)
{
return new ActionExecutor<T>(action);
}
public IActionExecutor Create<T1, T2>(Action<T1, T2> action)
{
return new ActionExecutor<T1, T2>(action);
}
// ... and so on
}
现在用法如下:
_subscriptions.Add(ActionExecutor.Create(a));
_subscriptions.Add(ActionExecutor.Create(b));
_subscriptions.Add(ActionExecutor.Create(c));