0

我有一个包含很多功能的类,称为Record. 在系统中存在两种基本类型的记录,它们的主键是uint,主键是Guid

该类Record包含我需要的所有功能,除了一个属性。Record.ID允许开发人员将当前主键读取为正确的类型(uintGuid)。

为了实现这一点,我必须创建三个这样的类(简化示例):

class Record {
    ... lots of code ...
}

class RecordInt : Record {
     public uint ID { get; set; }
}

class RecordGuid : Record {
     public Guid ID { get; set; }
}

这工作正常,但它引入了一个问题,即数据模型不能只创建一个通用Record实例。他们必须知道派生类是否期望RecordIntRecordGuid. 所以我为这样的模型添加了一个模板参数。

class abstract class Model<T> : were T : Record, new()
{
   ... lots of generic code that uses T ...

   // example
   public List<T> Find(...) { 
      .. find a record ...
      return new List<T>(); 
   }
}

这给我带来的问题不仅仅是拥有两种Record类型的好处。现在,当我实例化一个模型时,代码必须知道Record需要什么类型。如果这发生在应该是通用的部分中,那么我必须添加另一个模板参数。

过了一段时间,我发现开始有很多使用模板参数的方法。只是这样可以将类型传递给Model<RecordGuid>,有时我必须将模板参数传递到几个方法调用的链中,然后才能到达真正需要它的代码。

有没有比我正在做的更有效的模式?

编辑:

Model使用模板参数的一个原因是它需要具有返回Record. 在 C# 中,您不能强制List<Record>转换为,List<RecordGuid>因此我不得不使用模板参数作为返回类型作为List<T>.

4

1 回答 1

2

我决定创建一个新类来表示主键,并让该类控制该TypeID 的状态。

这将允许我只创建一个类来表示Record该类可以支持一个uintGuid主键。这也意味着Model该类不再需要模板参数,这导致其他依赖的源代码Model也不需要模板参数。

这是我PrimaryValue正在使用的课程。

/// <summary>
/// Used to store the value of the primary key for a table.
/// </summary>
public sealed class PrimaryValue
{
    /// <summary>
    /// The raw value
    /// </summary>
    private object _value;

    /// <summary>
    /// The required type.
    /// </summary>
    private Type _type;

    /// <summary>
    /// True if a Guid type.
    /// </summary>
    public bool IsGUID
    {
        get
        {
            return _type == typeof(Guid);
        }
    }

    /// <summary>
    /// Type if a uint type.
    /// </summary>
    public bool IsInteger
    {
        get
        {
            return _type == typeof(uint);
        }
    }

    /// <summary>
    /// True if the value is empty.
    /// </summary>
    public bool Empty
    {
        get
        {
            if (_type == typeof(uint))
            {
                return (uint)_value == 0;
            }
            return (Guid)_value == Guid.Empty;
        }
    }

    /// <summary>
    /// Constructor
    /// </summary>
    public PrimaryValue(Type pType)
    {
        _type = pType;
        if (pType == typeof(uint))
        {
            _value = 0;
        }
        else if (pType == typeof(Guid))
        {
            _value = Guid.Empty;
        }
        else
        {
            throw new ModelException("Type not supported by PrimaryValue.");
        }
    }

    /// <summary>
    /// UINT constructor.
    /// </summary>
    public PrimaryValue(uint pValue)
    {
        _value = pValue;
        _type = typeof(uint);
    }

    /// <summary>
    /// GUID constructor
    /// </summary>
    public PrimaryValue(Guid pValue)
    {
        _value = pValue;
        _type = typeof(Guid);
    }

    /// <summary>
    /// Copy constructor.
    /// </summary>
    public PrimaryValue(PrimaryValue pValue)
    {
        _value = pValue._value;
        _type = pValue._type;
    }

    public void set(PrimaryValue pValue)
    {
        if (_type == pValue._type)
        {
            _value = pValue._value;
            return;
        }

        throw new ModelException("PrimaryValues are not of the same type.");
    }

    /// <summary>
    /// Assigns a UINT value.
    /// </summary>
    public void set(uint pValue)
    {
        if (_type == typeof(uint))
        {
            _value = pValue;
            return;
        }

        throw new ModelException("PrimaryValue is not a UINT type.");
    }

    /// <summary>
    /// Assigns a GUID value.
    /// </summary>
    public void set(Guid pValue)
    {
        if (_type == typeof(Guid))
        {
            _value = pValue;
            return;
        }

        throw new ModelException("PrimaryValue is not a GUID type.");
    }

    /// <summary>
    /// Returns the raw value.
    /// </summary>
    public object get()
    {
        return _value;
    }

    /// <summary>
    /// Gets the ID as UINT.
    /// </summary>
    public uint ToInteger()
    {
        if (_type != typeof(uint))
        {
            throw new ModelException("PrimaryValue is not a UINT type.");
        }
        return (uint)_value;
    }

    /// <summary>
    /// Gets the ID as GUID.
    /// </summary>
    public Guid ToGuid()
    {
        if (_type != typeof(Guid))
        {
            throw new ModelException("PrimaryValue is not a GUID type.");
        }
        return (Guid)_value;
    }

    /// <summary>
    /// Checks if two IDs are equal.
    /// </summary>
    public static bool operator ==(PrimaryValue A, PrimaryValue B)
    {
        if (A._value.GetType() == B._value.GetType())
        {
            return A._value == B._value;
        }

        throw new ModelException("Can not compare PrimaryValues of different types.");
    }

    /// <summary>
    /// Checks if two IDs are not equal.
    /// </summary>
    public static bool operator !=(PrimaryValue A, PrimaryValue B)
    {
        if (A._value.GetType() == B._value.GetType())
        {
            return A._value != B._value;
        }

        throw new ModelException("Can not compare PrimaryValues of different types.");
    }

    /// <summary>
    /// Convertion to UINT.
    /// </summary>
    public static implicit operator uint(PrimaryValue A)
    {
        return A.ToInteger();
    }

    /// <summary>
    /// Convertion to Guid.
    /// </summary>
    public static implicit operator Guid(PrimaryValue A)
    {
        return A.ToGuid();
    }

    /// <summary>
    /// Convertion to string.
    /// </summary>
    public static implicit operator string(PrimaryValue A)
    {
        return A._value.ToString();
    }

    /// <summary>
    /// Convert to string.
    /// </summary>
    public override string ToString()
    {
        return _value.ToString();
    }

    /// <summary>
    /// Hashcode
    /// </summary>
    public override int GetHashCode()
    {
        return _value.GetHashCode();
    }
}
于 2013-05-21T16:50:48.510 回答