Возврат анонимного из Func <T>в качестве параметра в .Select () - PullRequest
4 голосов
/ 04 мая 2011

Ради "постобработки" в методе я хочу импортировать в метод дополнительную функцию.

Как импортировать 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 ]

3 голосов
/ 04 мая 2011

Анонимные типы действительно предназначены только для локального использования. В строго типизированных языках типы, которые не могут быть строго типизированы, на самом деле не поощряются для общего использования ... Они просто часть небольшого танца c # в динамическом мире.

У вас есть два варианта.

Создать сильный тип.

  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
  }

Или обратитесь к нему как к объекту. Затем используйте отражение, чтобы получить данные - я бы не рекомендовал это.

2 голосов
/ 04 мая 2011

Не могли бы вы добавить еще один универсальный параметр в BindControl?Например:

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

Обновление

После вашего обновления я бы посоветовал не использовать дженерики таким образом.Возможно, вам удастся заставить его работать через BindControl<AlbumQuery, Album, Func<Album, dynamic>>, но я бы посоветовал вам передавать объекты запроса напрямую, используя полиморфизм, а не обобщенные таким образом.

1 голос
/ 04 мая 2011

Вот ссылка на документацию MSDN для выбора:
http://msdn.microsoft.com/en-us/library/bb548891.aspx

В соответствии с этим формат:

Func<TSource, TResult> selector

В вашем случае TResultбыл бы ваш параметр U, я верю.

ОБНОВЛЕНИЕ: зачем вам нужен анонимный тип.Разве этого недостаточно, чтобы иметь возможность отправлять предикатное выражение в виде функции?

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");
1 голос
/ 04 мая 2011

Вы пробовали это, не уверены, будет ли это работать?

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();
}
...