代表们对通用操作,其中通用型是未知的。 如何创建类似的东西?(Delegates to gene

2019-08-01 10:42发布

假设我有下面的代码。

static class Store<T> {
    public static T A;
    public static T B;
    public static T C;
}

public static class Store {
    public static Value A = new Value(<T>(v) => Store<T>.A = v); //just an example of what I want
    public static Value B = new Value(<T>(v) => Store<T>.B = v); //just an example of what I want
    public static Value C = new Value(SetC<T>);  //just an example of what I want

    public static void SetA<T>(T value) { Store<T>.A = value; }
    public static void SetB<T>(T value) { Store<T>.B = value; }
    public static void SetC<T>(T value) { Store<T>.C = value; }
}

public class Value {
    Action<T><T> _valueChanger; //just an example of what I want
    public Value(Action<T><T> valueChanger) { //just an example of what I want
        _valueChanger = valueChanger;
    }

    public void SetValue<T> (T value) {
        _valueChanger<T>(value); //just an example of what I want
    }
}

我想要写Store.A.SetValue(42)以使该值被保存到Store<int>.A 。 我可以写什么,而不是由“只是我想要的一个例子”标记,以做到这一点的线? (我想探索不涉及字典或者类似的解决方案)

改写这样的问题:我想修改类Value (定义一些字段,写一个构造函数和写入方法Value.SetValue(T值)),则构造类型值(A,B,C)以这样的方式的三个不同的变量当调用Store.A.SetValue(42)的值Store<int>.A被改变为42。

类的另一种变化:

static class Holder<T> {
    T Value { get; set; }
}

static class Store2<T> {
    public static Holder<T> A = new Holder<T>();
    public static Holder<T> B = new Holder<T>();
    public static Holder<T> C = new Holder<T>();
}

public static class Store2 {
    public static Value A = new Value2(Store2<>.A); //just an example of what I want
    public static Value B = new Value2(Store2<>.B); //passing non-specific generic expression
    public static Value C = new Value3({TFree}() => Store2<TFree>.C); //just an example of what I want
}

public class Value2 { //Non-generic class!
    Holder{TFree}<TFree> _holder; //just an example of what I want
    public Value(Holder{TFree}<TFree> holder) { //just an example of what I want
        _holder = holder;
    }

    public void SetValue<T> (T value) {
        _holder{T}.Value = value; //just an example of what I want
    }
}

public class Value3 { //Non-generic class! (Another variation)
    Func{TFree}<Holder<TFree>> _holderFactory; //just an example of what I want

    public Value(Func{TFree}<Holder<TFree>> holderFactory) { //just an example of what I want
        _holderFactory = holderFactory;
    }

    public void SetValue<T> (T value) {
        Holder<T> holder = _holderFactory{T}(); //just an example of what I want
        holder.Value = value; 
    }
}

解决方案:使用回答另一个问题(一个简单的反射免费收集,免费的解决方案被发现仿效代表在C#免费泛型参数和仿效C#中的自由泛型类型参数的代表 )。 解决的办法是委托给通用操作,其中通用型是未知的。 如何创建类似的东西? 。

Answer 1:

使用一个数组来存储的价值和使用索引通过属性访问它们

public static class Store<T>
{
    public static readonly T[] Values = new T[3];
    public static T A { get { return Values[0]; } set { Values[0] = value; } }
    public static T B { get { return Values[1]; } set { Values[1] = value; } }
    public static T C { get { return Values[2]; } set { Values[2] = value; } }
}

public static class Store
{
    public static readonly Value A = new Value(0);
    public static readonly Value B = new Value(1);
    public static readonly Value C = new Value(2);
}

public class Value
{
    private int _index;

    public Value(int index)
    {
        _index = index;
    }

    public void SetValue<T>(T value)
    {
        Store<T>.Values[_index] = value;
    }

    public T GetValue<T>()
    {
        return Store<T>.Values[_index];
    }
}

由于构造函数Value是不知道有任何泛型类型参数的,你不能有一个特定的任何参考Store<T>


UPDATE

要注意的是副本的事实Store<T>会为您提供为每个不同类型的参数来创建T 。 看到这个例子

Store.A.SetValue(42);
Store.A.SetValue("Douglas Adams");
Store.A.SetValue(new DirectoryInfo(@"C:\"));
Store.A.SetValue(new List<int>());

var x1 = Store.A.GetValue<int>();           // --> 42
var x2 = Store.A.GetValue<string>();        // --> "Douglas Adams"
var x3 = Store.A.GetValue<DirectoryInfo>(); // --> DirectoryInfo{ C:\ }
var x4 = Store.A.GetValue<List<int>>();     // --> List<int>{ Count = 0 }

通过使用调试器,你会看到四个不同的值存储在A在同一时间! 原因的这些四种型动物A's存在四种不同影响Store<T>



Answer 2:

原来,这个问题是可以解决的。 麦克-Z给了我委托对仿制方法问题几乎正确的解决方案( 仿效C#中的自由泛型类型参数的代表 ),我修改为完整的解决方案:( 仿效C#提供免费泛型类型参数的代表 ) 。

该解决方案这个问题变得很容易。 接口可以包含通用的方法,我们可以使用接口值的变量来存储指向泛型方法不指定具体类型参数。 下面的代码利用了Store<T>类,而不修改和使用ISetter接口和ASetter / BSetter / CSetter “封闭”,以容纳不同的通用成员的引用。 的Value类存储在一个的参考文献ISetter -typed变量和使用通用的构件,其中_setter链接一旦类型参数T变得可用。

public interface ISetter {
    void SetValue<T>(T value);
}

public static class Store {
    public static Value A = new Value(new ASetter());
    public static Value B = new Value(new BSetter());
    public static Value C = new Value(new CSetter());

    class ASetter : ISetter {
        public void SetValue<T>(T value) { Store<T>.A = value; }
    }
    class BSetter : ISetter {
        public void SetValue<T>(T value) { Store<T>.B = value; }
    }
    class CSetter : ISetter {
        public void SetValue<T>(T value) { Store<T>.C = value; }
    }
}

public class Value {
    ISetter _setter;

    public Value(ISetter setter) {
        _setter = setter;
    }

    public void SetValue<T> (T value) {
        _setter.SetValue<T>(value);
    }
}


文章来源: Delegates to generic operations where the generic type is unknown. How to create something like that?