Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在一个列表中为不同类型的值设计工厂模式?_C#_Generics_Design Patterns_Collections_Factory - Fatal编程技术网

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

C# 如何在一个列表中为不同类型的值设计工厂模式?,c#,generics,design-patterns,collections,factory,C#,Generics,Design Patterns,Collections,Factory,我需要设计一个包含不同类型值(双精度、字符串、日期时间等)的数据结构。类型列表由用户动态创建。应根据该列表创建另一个值列表。 然后这个值的“记录”将由WCF发送并存储在动态创建的db表中。我从用c#设计这个解决方案开始。我的当前状态如下所示。我对目前的解决方案不满意,尤其是工厂和枚举。有没有更好的方法把事情做好 我的类型的枚举: public enum ValueType { Decimal, String, Boolean }; 然后接口: public interface IValueTy

我需要设计一个包含不同类型值(双精度、字符串、日期时间等)的数据结构。类型列表由用户动态创建。应根据该列表创建另一个值列表。 然后这个值的“记录”将由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();
    }
}
公共抽象类ValueType:IValueType
{
保护T_值;
公共价值类型(T值)
{
_价值=价值;
}
公共对象数据
{
获取{返回_值;}
}
公共价值类型
{
获取{return null;}
}
公共T值{get;私有集;}
公共重写字符串ToString()
{
返回_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)
    {}
}
公共类DecimalValueType:ValueType
{
公共小数值类型(十进制val):基数(val)
{}
公共小数值类型(双val):基数((十进制)val)
{}
公共小数值类型(int val):基数((十进制)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;
    }
}
公共静态类ValueTypeFactory
{
私有静态字典dictValueType=新字典()
{
{ValueType.Decimal,typeof(DecimalValueType)},
{ValueType.String,typeof(StringValueType)},
{ValueType.Boolean,typeof(BooleansValueType)}
};
私有静态字典dictSimple=newdictionary()
{
{typeof(decimal),typeof(DecimalValueType)},
{typeof(double),typeof(DecimalValueType)},
{typeof(int),typeof(DecimalValueType)},
{typeof(string),typeof(StringValueType)},
{typeof(bool),typeof(BooleansValueType)}
};
公共静态IValueType MakeByValueType(ValueType类型,参数对象[]初始值)
{
IValueType retObject=null;
if(dictValueType.ContainsKey(类型))
{
类型t=dictValueType[类型];
retObject=(IValueType)Activator.CreateInstance(t,initValues);
}
返回对象;
}
公共静态IValueType MakeByType(参数对象[]初始值)
{
IValueType retObject=null;
如果(initValues.Length>0)
{
类型Type=initValues[0]。GetType();
if(dictSimple.ContainsKey(类型))
{
类型t=简单[类型];
retObject=(IValueType)Activator.CreateInstance(t,initValues);
}
}
返回对象;
}
}
样本使用:

    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"));
List lista=新列表();
添加(新的小数点类型(12));
添加(新的StringValueType(“测试”));
Add(新的BooleansValueType(true));
添加(ValueTypeFactory.MakeByValueType(ValueType.Decimal,10.1));
添加(ValueTypeFactory.MakeByType(5.12));
Add(ValueTypeFactory.MakeByType(“Test2”));

我很乐意接受任何建议。

这里有一个更简单的解决方案,它涵盖了您文章中的用法,并避免了
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); }

}

我有一种“过度设计”的感觉。最有可能的情况是,您必须多解释一点您的用例(以及为什么您首先要这么做)。例如,这在什么方面比列表和白名单更好呢?在桌面应用程序中,我收到了200多个实时参数的记录,其中有一些时间步长。我的目标是在这个桌面应用程序(用mfc编写)和web应用程序(连接到sql数据库)之间架起一座桥梁。我决定使用wcfapi。web应用程序的管理员创建他希望在db中包含的参数列表。因此,我必须根据create表在其类型中列出这些参数,并向WCF服务发送一个适当的值列表。
IValueType
接口看起来没用。我只需要一个带有受保护构造函数的
公共抽象类ValueType
。然后,如果客户机代码只希望自动推断类型,而我不会实现
MakeByValueType
操作,那么我将使用依赖于反射的工厂来查找具体的
ValueType
实现。这与
新的ConcreteValueType(…)
相同。我认为需要使用IValueType将所有派生类放到一个集合中—我不能将ValueType的泛型版本(使用不同的T)添加到一个集合中。关于枚举-用户必须有选择权(一些不同类型的列表)选择所需的参数类型。所以我在choosed类型和由静态方法MakeByValueType创建的IValueType实例之间建立了连接。我错了吗?很好的解决方案!非常干净优雅。隐式运算符的良好使用。非常感谢你!
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();
    }
}
1 - Decimal
Test - String
True - Boolean
10.1 - Decimal
5.12 - Decimal
Test2 - String