2014-09-17 3 views
0

У меня есть два метода в моем DAL, которые идентичны и возвращают строку базы данных на основе первичного ключа, поданного в качестве параметра. Контекст БД - linqtoSQL. Один передается в строковом параметре, а второй - в параметре int. Я думаю, что для создания единого метода, который принимает строку или int, но не уверен, как это сделать, должно быть запрещено использовать generics.Объединить два метода в единый общий метод

/// <summary> 
    /// Select table row by integer Primary Key Value 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="id">The PK value to search for</param> 
    /// <returns>Single matching PK to id</returns> 
    public T SelectRowByPk<T>(int id) where T : class 
    { 
     using (var dc = new DBDataContext()) 
     { 
      // Get the table by the type passed in 
      var table = dc.GetTable<T>(); 
      // Get the metamodel mappings (database to domain objects) 
      MetaModel modelMap = table.Context.Mapping; 
      // Get the data members for this type 
      ReadOnlyCollection<MetaDataMember> dataMembers = 
      modelMap.GetMetaType(typeof (T)).DataMembers; 
      // Find the primary key field name by checking for IsPrimaryKey 
      string pk = (dataMembers.Single(m => m.IsPrimaryKey)).Name; 

      // Return a single object where the id argument matches the primary key 
      field value 
      return table.SingleOrDefault(delegate(T t) 
              { 
               int memberId = 

    Convert.ToInt16(t.GetType().GetProperty(pk).GetValue(t, null)); 
               return memberId == id; 
              }); 
     } 
    } 

    /// <summary> 
    /// Select table row by Varchar Primary Key Value 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="id">The PK value to search for</param> 
    /// <returns>Single matching PK to id</returns> 
    public T SelectRowByVarcharPk<T>(string id) where T : class 
    { 
     using (var dc = new DBDataContext()) 
     { 
      // Get the table by the type passed in 
      var table = dc.GetTable<T>(); 
      // Get the metamodel mappings (database to domain objects) 
      MetaModel modelMap = table.Context.Mapping; 
      // Get the data members for this type 
      ReadOnlyCollection<MetaDataMember> dataMembers = 
    modelMap.GetMetaType(typeof(T)).DataMembers; 
      // Find the primary key field name by checking for IsPrimaryKey 
      string pk = (dataMembers.Single(m => m.IsPrimaryKey)).Name; 

      // Return a single object where the id argument matches the primary key 
field value 
      return table.SingleOrDefault(delegate(T t) 
      { 
       string memberId = 
        t.GetType().GetProperty(pk).GetValue(t, null).ToString(); 
       return memberId == id; 
      }); 
     } 
    } 

ответ

1

Вы не можете использовать дженерики непосредственно объединить два метода в один, однако вы можете использовать немного рефакторинга в сочетании с обобщениями, чтобы иметь чистый дизайн:

сделать приватный метод, который делает тяжелую работу с двумя общие параметры, один для типа объекта и для первичного ключа типа:

private T SelectRowById<T, TId>(TId id) where T : class 
    { 
     using (var dc = new DBDataContext()) 
     { 
      // Get the table by the type passed in 
      var table = dc.GetTable<T>(); 
      // Get the metamodel mappings (database to domain objects) 
      MetaModel modelMap = table.Context.Mapping; 
      // Get the data members for this type 
      ReadOnlyCollection<MetaDataMember> dataMembers = 
    modelMap.GetMetaType(typeof(T)).DataMembers; 
      // Find the primary key field name by checking for IsPrimaryKey 
      string pk = (dataMembers.Single(m => m.IsPrimaryKey)).Name; 

      // Return a single object where the id argument matches the primary key 
field value 
      return table.SingleOrDefault(delegate(T t) 
      { 
       var memberId = 
        (TId)t.GetType().GetProperty(pk).GetValue(t, null); 
       return memberId == id; 
      }); 
     } 
    } 

После этого вы можете объявить два общих методы для конкретного типа идентификаторов, которые используют этот частный метод:

public T SelectRowById<T>(string id) where T : class 
{ 
    return SelectRowById<T, string>(id); 
} 

public T SelectRowById<T>(int id) where T : class 
{ 
    return SelectRowById<T, int>(id); 
} 

Таким образом, у вас будет чистый публичный интерфейс с минимальным дублированием кода.

-1
public T SelectRowByPk<T>(T id) 
{ 
    //you'll need to do some run-time type checking of 'id' here since string and int 
    //can't be constrained by a type parameter constraint in the same method 
} 

Одна из точек с указанием параметра типа так, что один может иметь типы динамических параметров. В этом примере «id» становится любым типом, который вы указываете.

Смежные вопросы