从Func <t>返回匿名作为.Select()</t>中的参数

时间:2011-05-04 08:38:47

标签: c# linq generics c#-3.0 anonymous-types

为了对方法进行“后处理”,我想将一个额外的函数导入到方法中。

如何导入返回匿名类型的Func作为.Select扩展方法的参数?

表达方式如下:

p => new
{
    ThumnailUrl = p.PicasaEntry.Media.Thumbnails[0].Attributes["url"],
    ImageUrl = p.PhotoUri
}

并且需要在参数?????中使用并在.Select(?????)

执行
private void BindControl<T, U>(string uri, DataBoundControl target, ?????)
    where T : KindQuery, new()
    where U : PicasaEntity, new()
{
    PicasaFeed feed = CreateFeed<T>(uri);
    albumList.DataSource = GetPicasaEntries<U>(feed).Select(?????);
    albumList.DataBind();
}

更新:

最后我想把它称为:

    string albumUri = PicasaQuery.CreatePicasaUri(PicasaUserID, PicasaAlbumID);
    BindControls<AlbumQuery, Album>(albumUri, albumList, ?????);

    string photoUri = PicasaQuery.CreatePicasaUri(PicasaUserID, PicasaAlbumID);
    BindControls<PhotoQuery, Photo>(photoUri, slideShow, ?????);

其他方法如下:

private PicasaFeed CreateFeed<T>(string uri) 
   where T : KindQuery, new()
{
    PicasaFeed feed = null;

    try
    {
        PicasaService service = new PicasaService(PicasaApplicationName);
        T query = new T();
        query.BaseAddress = uri;
        feed = service.Query(query);
    }
    catch (Exception ex)
    {
        //exception handling not shown
    }

    return feed;
}



private IEnumerable<T> GetPicasaEntries<T>(PicasaFeed feed) 
     where T : PicasaEntity, new()
{
    if(feed == null){
        return null;
    }

    IEnumerable<T> entries = null;
    string cacheKey = feed.Id.ToString();

    if(Cache.Get(cacheKey) == null)
    {
        entries = feed.Entries.Select(x => new T() { AtomEntry = x }).ToList();
    Cache.Insert(cacheKey, entries, 
              null, Cache.NoAbsoluteExpiration, new TimeSpan(0,20,0));
    }

    return entries;
}

4 个答案:

答案 0 :(得分:3)

匿名类型实际上只是为本地使用而设计的。在强类型语言中,不能强烈键入的类型并不是一般用途的鼓励...它们只是动态世界中c#s little dance的一部分。

你有两个选择。

创建一个强类型。

  class Entry
  {
    public string ThumnailUrl { get; set; }
    public string ImageUrl { get; set; }
  }

然后使用:

  p => new Entry 
  {
     ThumnailUrl = p.PicasaEntry.Media.Thumbnails[0].Attributes["url"],
     ImageUrl = p.PhotoUri
  }

或者将其称为对象。然后使用反射来获取数据 - 我不建议这样做。

答案 1 :(得分:2)

您可以向BindControl添加另一个通用参数吗?例如:

private void BindControl<T, U, V>(string uri, DataBoundControl target,
                                  Func<U, V> selector)

<强>更新

在您更新后,我建议不要以这种方式使用泛型。您可以通过BindControl<AlbumQuery, Album, Func<Album, dynamic>>使其工作,但我建议您直接传递查询对象,利用多态,而不是以这种方式使用泛型。

答案 2 :(得分:1)

您是否尝试过此操作,不确定它是否有效?

private void BindControl<T, U, V>(string uri, DataBoundControl target, Func<U,V> selector)
    where T : KindQuery, new()
    where U : PicasaEntity, new()
{
    PicasaFeed feed = CreateFeed<T>(uri);
    albumList.DataSource = GetPicasaEntries<U>(feed).Select(selector);
    albumList.DataBind();
}

答案 3 :(得分:1)

以下是选择的MSDN文档的链接:
http://msdn.microsoft.com/en-us/library/bb548891.aspx

根据该格式:

Func<TSource, TResult> selector

在你的情况下,我认为TResult将是你的U参数。

更新: 为什么需要匿名类型。是不是能够以func的形式发送谓词表达式?

private void BindControl<T, U>(string uri, DataBoundControl target, Func<U, bool> selector)
        where T : KindQuery, new()
        where U : PicasaEntity, new()
    {
        PicasaFeed feed = CreateFeed<T>(uri);
        var feeds = GetPicasaEntries<U>(feed).Select(U);

    }

BindControl<AlbumQuery,Album>(albumUri,albumList,p=>p.Title=="Some title");