How to access all specific versions of a generic s

2019-08-29 18:57发布

问题:

Let's say I have the following static class:

public static class Foo<T>
{
    private static T Baz;

    /* other members */

    public static void Bar()
    {
        //do something with Baz
    }
}

Is there a built-in way to call Bar() for all specific versions of the generic class without knowing the type parameters that were used? That is, if the consumer of Foo<T> has used it as Foo<Larry>, Foo<Curly> and Foo<Moe>, how can I call all the Foo<Larry>.Bar(), Foo<Curly>.Bar() etc. methods automatically without explicitly specifying the generic types?

回答1:

That is not possible. Use the static constructor of Foo<T> to maintain a global list of Baz values. That global list must be rooted in a static variable that lives outside of Foo<T>.



回答2:

The number of possibilities for T is infinite. There is no way to know what might be used for T. You can, using the static constructor, track the types that have already been used for T and perform an operation against all of those types.

Here I created a class with a static variable containing a list of Actions. Action matches the signature of void Bar(), so to call a different signature, use a different type i.e. Action<string> to call void Bar(string x) or Func<int,string> to call string Bar(int val).

public static class FooTracker
{
    public static List<Action> AllBars = new List<Action>();
    public static void CallAllBars()
    {
        AllBars.ForEach(v => v());
    }
}

public static class Foo<T>
{
    static Foo()
    {
        FooTracker.AllBars.Add(() => Bar());
    }

    public static void InitFoo() 
    { 
        // do nothing other than cause static constructor to run
    }


    private static T Baz;

    /* other members */

    public static void Bar()
    {
        //do something with Baz
        Debug.Print(typeof(T).Name);
    }
}

If you use the code below to call this, you will observe that Foo<Curly>.Bar() isn't called because the static constructor isn't run until after the CallAllBars() call.

Foo<Larry>.InitFoo();
Foo<Moe>.InitFoo();

FooTracker.CallAllBars();

Foo<Curly>.InitFoo();