4

こんにちは私は、パラメータの数とタイプが不明なアクションにジェネリックをキャストしようとしています

現時点では次のようになります。

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-ClassList<Subscription>Fourth-Class

4

2 に答える 2

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);
于 2013-01-25T08:54:10.397 に答える
1

あなたはそれをそのようにすることはできません。Subscription<Action<int>>をと同じリストに入れることはできませんSubscription<Action<string, Foo>>

次のようなインターフェイスを作成し、それらを3番目のクラスに保存することをお勧めします。

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]);
    }
}

3番目のクラスには、次のリストがありますIActionExecutor

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));
于 2013-01-25T08:45:26.210 に答える