C# 将产量线提取到常用方法中

C# 将产量线提取到常用方法中,c#,.net,subsonic,subsonic3,yield,C#,.net,Subsonic,Subsonic3,Yield,我们在代码中使用了自动生成的代码(SubSonic3和Repository模式),有很多行是这样的 public IEnumerable<MyModels.StatusLookup> GetAll() { var results = Database.Current.pStatusLookupLoadAll() .ExecuteTypedList<MyModels.StatusLookup>(); if (r

我们在代码中使用了自动生成的代码(SubSonic3和Repository模式),有很多行是这样的

public IEnumerable<MyModels.StatusLookup> GetAll()
    {
        var results = Database.Current.pStatusLookupLoadAll()
            .ExecuteTypedList<MyModels.StatusLookup>();
        if (results.IsNull()) yield break;
        foreach (var m in results)
        {
            ..Common logic lines...
            ..Common logic lines...
            yield return m;
        }
    }
public IEnumerable GetAll()
{
var results=Database.Current.pStatusLookupLoadAll()
.ExecuteTypedList();
if(results.IsNull())产生中断;
foreach(结果中的var m)
{
…通用逻辑线。。。
…通用逻辑线。。。
收益率m;
}
}
我想做的是把收益线重构成一个通用的方法。但我不知道我是否可以,因为产量的工作方式

然后,当我们有自定义代码在存储库自动生成的代码之外调用db时,我就可以在加载的模型对象上调用这个公共方法

public IEnumerable<Books> GetByFancy(int anInteger)
{
    DB db = Database.Current;
    var r = from b in db.Books
            join a in db.Authors on b.AuthorId equals a.AuthorId
            where a.AuthorId == anInteger
            select b;

    if (r.IsNull()) yield break;
    foreach (var m in r)
    {
        m.AcceptChanges();
        yield return m;
    }
}
public IEnumerable GetByFancy(整数)
{
DB=Database.Current;
var r=从数据库中的b开始
在db中加入a。b.AuthorId上的作者等于a.AuthorId
其中a.AuthorId==整数
选择b;
如果(r.IsNull())产生中断;
foreach(r中的var m)
{
m、 接受变化();
收益率m;
}
}
因此,上面的示例中有公共重复行,我想进行一个公共方法调用来删除公共重复代码行


这是我得到的一个例外

System.InvalidCastException : Unable to cast object of type '<AcceptChangesAndYield>d__6' to type 'System.Collections.Generic.IEnumerable`1[MyModels.StatusLookup]'.

public IEnumerable<MyModels.StatusLookup> GetAll()
{
    var results = Database.Current.pStatusLookupLoadAll()
        .ExecuteTypedList<MyModels.StatusLookup>();
    return (IEnumerable<MyModels.StatusLookup>)results.AcceptChangesAndYield();
}
System.InvalidCastException:无法将类型为“d__6”的对象强制转换为类型为“System.Collections.Generic.IEnumerable`1[MyModels.StatusLookup]”。
公共IEnumerable GetAll()
{
var results=Database.Current.pStatusLookupLoadAll()
.ExecuteTypedList();
返回(IEnumerable)结果;
}
这是我尝试的扩展方法

public static class BaseModelExtensions
{
    public static IEnumerable<MyModels.BaseModel> AcceptChanges(this IEnumerable<MyModels.BaseModel> obj)
    {
        if (obj.IsNull()) yield break;
        foreach (var m in obj)
        {
            m.AcceptChanges();
            yield return m;
        }
    }

    public static IEnumerable<MyModels.Interfaces.ILookup> AcceptChangesAndYield(this IEnumerable<MyModels.Interfaces.ILookup> obj)
    {
        if (obj.IsNull()) yield break;
        foreach (var m in obj)
        {
            yield return m;
        }
    }
}
公共静态类BaseModelExtensions
{
公共静态IEnumerable AcceptChanges(此IEnumerable obj)
{
if(obj.IsNull())产生中断;
foreach(obj中的var m)
{
m、 接受变化();
收益率m;
}
}
公共静态IEnumerable AcceptChanges和产量(此IEnumerable obj)
{
if(obj.IsNull())产生中断;
foreach(obj中的var m)
{
收益率m;
}
}
}

更新:您的问题与
产量
关键字无关。它与类型差异有关

您的
AcceptChangesAndYield
方法返回实现
IEnumerable
的类型的对象(实际上它是编译器生成的类型,但这并不重要)。在方法调用中,您试图将其向下转换为更具体的
IEnumerable

IEnumerable
界面是协变的,这将允许您向上转换到不太特定的类型;e、 例如,您可以从
列表
转换为
IEnumerable
(无论如何,在.NET4.0中)。编译器生成的用于提供
acceptchanges和yield
方法返回值的类型仅实现
IEnumerable
,因此可以将结果强制转换为
IEnumerable
(例如),但不能转换为
IEnumerable

幸运的是,解决方案非常简单。重新定义
acceptchanges和yield
方法,如下所示:

// Note: We are using a generic type constraint on T.
public static IEnumerable<T> AcceptChangesAndYield<T>(this IEnumerable<T> obj)
    where T : MyModels.Interfaces.ILookup
{
    if (obj.IsNull()) yield break;
    foreach (var m in obj)
    {
        // Did you mean to put m.AcceptChanges() here?
        yield return m;
    }
}
public IEnumerable<MyModels.StatusLookup> GetAll()
{
    var results = Database.Current.pStatusLookupLoadAll()
        .ExecuteTypedList<MyModels.StatusLookup>();
    // Note: no need for a cast, as the return value is now
    // already strongly typed as IEnumerable<MyModels.StatusLookup>.
    return results.AcceptChangesAndYield();
}

原始答案:看起来你只是想要这个

IEnumerable<T> EnumerateResults<T>(IEnumerable<T> results)
{
    if (results.IsNull()) yield break;
    foreach (T result in results)
    {
        // ..Common logic lines...
        yield return result;
    }
}

对吧??还是我误解了你的问题?

你到底在问什么?你为什么想要收益率?你想要什么?是的,这个问题目前还不清楚。现在还不清楚您所展示的两个方法是什么样的,或者公共逻辑线是如何操作的;foreach(results中的var m){..公共逻辑线..公共逻辑线..产生返回m;}在第二个示例中,r永远不会为null(它可能是一个空的可枚举项)。而且,连接似乎是不必要的:从db.Books中的b.AuthorId==一个整数select byou的位置,我正试图做什么。我将发布一个“答案”,上面写着我尝试时得到的答案。原始帖子编辑了我尝试过的内容和我当前的问题。Thx@DavidW:看了你对这个问题的更新后,我很确定我理解你遇到的问题。试试我在更新中提出的建议,如果有帮助,请告诉我!
// Specific stuff
var results = BlahBlahBlah();

// Common stuff
return EnumerateResults(results);