为某些字段值和其他扩展点添加处理程序

时间:2011-07-11 20:10:08

标签: c#

我正在构建一个修复了数据模型的应用程序,但是人们(或者只是我)可以通过添加继承自基类的类来扩展它,这些类从db中的信息实例化并在服务中序列化。

我有三个问题区域(下面的示例代码中的案例1 2和3)。 案例#1我可以通过界面解决,但这对案例2或3没有帮助。

我认为代码示例会比我尝试解释更好;关于如何处理这个问题的任何想法,以便每个新的字段类型不需要手动添加到代码中的一堆地方?

    public class ManagerClass
{
    public ManagerClass()
    {

        public ManagerClass()
        {
        }

        //Case #1
        public void process(AllFields allFields)
        {
            foreach (Field field in allFields.Fields)
            {
                //Currently I need to add all extention types as seperate cases here manually
                //...this type of logic appears in several places in the code
                if (field.GetType().Name == "ExtendedField")
                {
                    //Have the extended field do something in a way particular to it
                }
                else
                {
                    //Have the base field do something the "normal" way
                }
            }
        }
        //Case #2
        //Here is another case where currently I am adding each case in by hand
        //fieldType is a string here because I am storing what type of field it is in the DB
        public void create(string value, string fieldType)
        {
            //Currently I need to add all extention types as seperate cases here manually
            if (fieldType == "ExtendedField")
            {
                //Create a ExtendedField
            }
            else
            {
                //Create a Field
            }
        }
    }
}

[DataContract]
//Case #3
[KnownType(typeof(ExtendedField))] //Currently I need to add all extention types here manually
public class AllFields
{
    private List<Field> fields;
    public AllFields(){}

    [DataMember]
    public List<Field> Fields
    {
        get { return fields; }
        set { fields = value; }
    }
}

[DataContract]
public class Field
{
    private string fieldValue;
    public Field(){}

    [DataMember]
    public string FieldValue
    {
        get { return fieldValue; }
        set { fieldValue = value; }
    }
}

[DataContract]
public class ExtendedField : Field
{
    private string someOtherAttribute;
    public ExtendedField(){}

    [DataMember]
    public string SomeOtherAttribute
    {
        get { return someOtherAttribute; }
        set { someOtherAttribute = value; }
    }
}

2 个答案:

答案 0 :(得分:2)

听起来你正在尝试构建一个微型可扩展性框架。考虑这样的事情,其中​​扩展逻辑由FieldHandler处理:

public class FieldHandler
{
   public virtual Field CreateField(string value, string fieldType){...}
}

// Case 2
Field field = null;
foreach (FieldHandler handler in m_handlers)
{
   if (handler.SupportsFieldType(fieldType))
   {
       field = handler.CreateField (value, fieldType);
       continue;
   }
}
if (field == null)
{
   // Create standard field.
   field = ...;
}

答案 1 :(得分:2)

对于可扩展的字段阅读:

使字段成为一个抽象类,并使所有常用方法都抽象化。从Field派生的类将精确指定这些方法的作用。

然后,您可以将这些派生类的对象传递回接受Field的方法,并且可以调用Field的方法,而无需担心正在使用的实际类。接口会更好,但是你没有为常用功能重用代码。

对于可扩展的字段创建:

您将始终必须在程序的边界处进行切换或某事以确定要创建的类。您的目标是仅在一个地方执行此操作。您的设计 - 根据数据库中的数据确定使用的工厂方法 - 是理想的选择。

研究制作一个有责任根据数据库数据创建Field对象的类,然后传递它。如果它是抽象的,你可以将它子类化并将其作为参数传递给方法,这些方法将通过调用类似fieldFactory.GetNewField(myParameter);来获取所需的数据。

对于可扩展序列化:

Research DataContractResolver。

提示:

如果你发现自己必须在多个地方(调用构造函数的地方)中打开Field的类型,那么你做错了。这方面的一个例子是您的进程(字段)方法。相反,Field或IField应该有一个抽象的Process方法。消费者只需调用Field.Process,而不关心它是如何实现的。

示例:

public abstract class Field
{
   public abstract void Process();
}

public class ExtendedField : Field
{
   public override void Process() { /*Extended Field Specific Stuff Here*/ }
}

//consumer code

public void DoStuffWithABunchOfFieldsOfUnknownType(IEnumerable<Field> fields)
{
   foreach (Field field in fields) { field.Process(); }
}