问题描述:

For the sake of "post processing" on a method, I want to import an extra function into a method.

How can I import a Func that returns an anonymous Type as a parameter for a .Select extension method?

The expression is anounymous like:

p => new

{

ThumnailUrl = p.PicasaEntry.Media.Thumbnails[0].Attributes["url"],

ImageUrl = p.PhotoUri

}

and needs to be used at parameter ????? and performed at .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();

}

update:

finally I want to call it like:

 string albumUri = PicasaQuery.CreatePicasaUri(PicasaUserID, PicasaAlbumID);

BindControls<AlbumQuery, Album>(albumUri, albumList, ?????);

string photoUri = PicasaQuery.CreatePicasaUri(PicasaUserID, PicasaAlbumID);

BindControls<PhotoQuery, Photo>(photoUri, slideShow, ?????);

the other methods are like:

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;

}

网友答案:

Anonymous types are really only designed for local use. In a strongly typed language types that can't be strongly typed are not really encouraged for general use... They are just a part of c#s little dance in the dynamic world.

You have two choices.

Create a strong type.

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

And then use :

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

Or refer to it as Object. Then use reflection to get the data out - I wouldn't recommend this.

网友答案:

Could you add another generic parameter to BindControl? For example:

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

Update

Following your update, I'd suggest not to use generics in this way. You may be able to get it working via BindControl<AlbumQuery, Album, Func<Album, dynamic>>, but I would suggest that you pass query objects directly, making use of polymorphism, instead of using generics in this way.

网友答案:

Did you try this, not sure whether it will work?

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();
}
网友答案:

Here is the link to the MSDN documentation for select:
http://msdn.microsoft.com/en-us/library/bb548891.aspx

According to that the format is:

Func<TSource, TResult> selector

In your case the TResult would be your U parameter I belive.

UPDATE: Why do you need to have a anonymous type. Is it not enough to be able to send in the predicate expression in the form of a 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");
相关阅读:
Top