如何在一个列表中为不同类型的值设计工厂模式?

时间:2015-10-29 10:52:57

标签: c# generics design-patterns collections factory

我需要设计一个包含不同类型值(双精度数,字符串,日期时间等)的数据结构。类型列表由用户动态创建。根据该列表,应创建另一个值列表。 然后这个"记录"值由WCF发送并存储在动态创建的db表中。我开始在c#中设计这个解决方案。我目前的状态如下所示。我对目前的解决方案不满意,特别是对于工厂和枚举。是否有更好的方法来做正确的事情?

我的类型的枚举:

public enum ValueType { Decimal, String, Boolean };

然后界面:

public interface IValueType
    {
        object Data { get; }
        string ToString();
        ValueType? Type { get; }
    }

基类:

public abstract class ValueType<T> : IValueType
{
    protected T _Value;

    public ValueType(T value)
    {
        _Value = value;
    }

    public object Data
    {
        get { return _Value; }
    }

    public ValueType? Type
    {
        get { return null; }
    }
    public T Value { get; private set; }
    public override string ToString()
    {
        return _Value.ToString();
    }
}

实施之一:

public class DecimalValueType : ValueType<decimal>
{
    public DecimalValueType( decimal val ) : base(val)
    {}
    public DecimalValueType(double val) : base((decimal)val)
    {}
    public DecimalValueType(int val) : base((decimal)val)
    {}
}

然后工厂:

public static class ValueTypeFactory
{
    private static Dictionary<ValueType, Type> dictValueType = new Dictionary<ValueType, Type>()
    {
        { ValueType.Decimal, typeof(DecimalValueType) },
        { ValueType.String, typeof(StringValueType) },
        { ValueType.Boolean, typeof(BooleansValueType) }
    };

    private static Dictionary<Type, Type> dictSimple = new Dictionary<Type, Type>()
    {
        { typeof(decimal), typeof(DecimalValueType) },
        { typeof(double), typeof(DecimalValueType) },
        { typeof(int), typeof(DecimalValueType) },
        { typeof(string), typeof(StringValueType) },
        { typeof(bool), typeof(BooleansValueType) }
    };

    public static IValueType MakeByValueType(ValueType type, params object[] initValues)
    {
        IValueType retObject = null;
        if (dictValueType.ContainsKey(type) )
        {
            Type t = dictValueType[type];
            retObject = (IValueType)Activator.CreateInstance(t,initValues);
        }
        return retObject;
    }

    public static IValueType MakeByType(params object[] initValues)
    {
        IValueType retObject = null;
        if ( initValues.Length > 0 )
        {
            Type type = initValues[0].GetType();
            if (dictSimple.ContainsKey(type))
            {
                Type t = dictSimple[type];
                retObject = (IValueType)Activator.CreateInstance(t, initValues);

            }
        }
        return retObject;
    }
}

样本使用:

    List<IValueType> lista = new List<IValueType>();
    lista.Add(new DecimalValueType(12));
    lista.Add(new StringValueType("Test"));
    lista.Add(new BooleansValueType(true));
    lista.Add(ValueTypeFactory.MakeByValueType(ValueType.Decimal, 10.1));
    lista.Add(ValueTypeFactory.MakeByType(5.12));
    lista.Add(ValueTypeFactory.MakeByType("Test2"));

我对任何建议都很满意。

1 个答案:

答案 0 :(得分:1)

这是一个更简单的解决方案,涵盖了帖子中的用法,避免了ValueType子类噪音:

public abstract class ValueType
{
    public enum Types { Decimal, String, Boolean };
    public abstract object Data { get; }
    public abstract Types Type { get; }
    private ValueType() {}

    protected class TypedValueType<T> : ValueType
    {
        private Types type;

        public TypedValueType(T value, Types type) : base()
        {
            this.Value  = value;
            this.type   = type;
        }

        public override object Data { get { return this.Value; } }
        public override Types Type { get { return this.type; } }
        public T Value { get; private set; }

        public override string ToString()
        {
            return this.Value.ToString();
        }

    }

    public static implicit operator ValueType(decimal value) { return new TypedValueType<decimal>(value, Types.Decimal); }
    public static implicit operator ValueType(double value) { return new TypedValueType<decimal>((decimal)value, Types.Decimal); }
    public static implicit operator ValueType(int value) { return new TypedValueType<decimal>((decimal)value, Types.Decimal); }
    public static implicit operator ValueType(string value) { return new TypedValueType<string>(value, Types.String); }
    public static implicit operator ValueType(bool value) { return new TypedValueType<bool>(value, Types.Boolean); }

}

样本用法:

public class Demo
{
    public static void Main()
    {
        List<ValueType> lista = new List<ValueType>();
        lista.Add(1);
        lista.Add("Test");
        lista.Add(true);
        lista.Add(10.1);
        lista.Add(5.12);
        lista.Add("Test2");
        foreach(var value in lista) Console.WriteLine(value.Data + " - " + value.Type.ToString());
        Console.ReadKey();
    }
}

由于您似乎想要限制可以包含的值的类型,嵌套的TypedValueType类被标记为受保护,ValueType构造函数被标记为私有。隐式运算符用于提供“工厂”逻辑,用于为要转换的值生成适当的类型TypeValueType子类。

以下是执行此操作作为控制台应用程序的输出:

1 - Decimal
Test - String
True - Boolean
10.1 - Decimal
5.12 - Decimal
Test2 - String