2009-12-19 112 views
2

我有一个仓储类两个通用的保存方法:如何编写处理单个对象和集合的通用Save()方法?

public void Save<T>(T entity) 
{ 
    _session.Save(entity); 
} 

public void Save<T>(IEnumerable<T> entities) 
{ 
    foreach (var item in entities) 
    { 
     _session.Save(item); 
    } 
} 

然而,当我使用Save(collection)(自动推断类型),它认识到它作为一个T而非IEnumerable<T>并尝试使用,以保存第一种方法。

我该如何编写这个保存方法以便它可以处理这两种情况,而无需我明确提供类型?

回答

4

将类型参数放在存储库上的类级别上,而不是在方法级别上,这样重载就不会含糊不清了。

class Repo<T> 
{ 
    public void Save(T entity) 
    { 
     _session.Save(entity); 
    } 

    public void Save(IEnumerable<T> entities) 
    { 
     foreach (var item in entities) 
     { 
      _session.Save(item); 
     } 
    } 
} 

你会使用这样的:

var repo = new Repo<Person>(); 

var p = new Person(); 
repo.Save(p); 

var ps = new Person[] { p }; 
repo.Save(ps); 
+0

如果我想保持无类型的存储库,该怎么办?我希望能够通过将类型传递给'Get()'来实例化存储库并查询任何实体。这为我省去了实例化同一个存储库的多个副本的麻烦,其中它们之间的唯一区别是类型。 – 2009-12-19 08:48:31

+0

为了澄清,我希望能够这样做:'var repo = new Repository(); repo.Get (); repo.Get (); repo.Get ();'代替:var repo1 = new Repository (); var repo2 = new Repository (); var repo3 = new Repository ();'。 – 2009-12-19 08:50:51

0

Whjy不屑于重载方法?是不是好做它喜欢:

public void Save<T>(T entity) 
{ 
    if (T is IEnumerable) 
    { 
     foreach (var item in entity) 
       _session..Save(item); 
    } else { 
     _session.Save(entity); 
    } 
} 
+0

这并不遵循SRP。参数的名称没有准确地描述它可能包含的值的事实是一个大的代码味道警告。 – 2009-12-19 03:17:03

+0

似乎优雅地工作的一种解决方案是将其分成两个具有不同签名的独立方法。 – 2009-12-19 03:32:43

1

你不能依靠类型推断这个特定的情况下。 <T>(T)将满足任何类型,因此推断不会继续搜索以找到更符合签名的更具体的约束条件。

0

你可以这样使用它也:

public void Save<T>(T entity) 
    { 
     if (typeof(T).GetInterfaces().Contains(typeof(IEnumerable))) 
     { 
      SaveEnumerable(entity as IEnumerable); 
     } 
     else 
     { 
      _session.Save(entity); 
     } 
    } 

    public void SaveEnumerable(IEnumerable entities) 
    { 
     foreach (var item in entities) 
     { 
      _session.Save(item); 
     } 
    } 

希望这有助于!

相关问题