2014-09-19 56 views
2

如何将扩展方法作为参数传递给类的构造函数,并让该类中的方法将该扩展用作扩展?将方法扩展作为参数传递

例如:这是含有一个IEnumerable扩展方法的文件:

namespace System.Collections.Generic 
{ 
    public static partial class IEnumerableMethodExtensions 
    { 
     /// <summary> 
     /// Used by IsImageFile to determine if a file is a graphic type 
     /// we care about. (Not an Extension Method, just a helper method) 
     /// </summary> 
     public static string[] GraphicFileExtensions = new string[] { ".png", ".bmp", ".gif", ".jpg", ".jpeg" }; 

     /// <summary> 
     /// Method Extension - specifies that FileInfo IEnumerable should only 
     /// return files whose extension matches one in GraphicFileExtensions[]. 
     /// </summary> 
     /// <param name="files"></param> 
     /// <returns></returns> 
     public static IEnumerable<FileInfo> IsImageFile(this IEnumerable<FileInfo> files) 
     { 
      foreach (FileInfo file in files) 
      { 
      string ext = file.Extension.ToLower(); 
      if (GraphicFileExtensions.Contains(ext)) 
       yield return file; 
     } 
    } 
} 

}

我希望能够通过IsImageFile()作为参数传递给一个构造到该对象,所以,在这类方法可以使用IsImageFile作为方法的扩展:

public class MainFileInfoSource 
{ 
    public MainFileInfoSource(List<DirectoryInfo> Directories, 
       ENUMERABLE_METHOD_EXTENSION_FILE_FILTER TheMethodExtension) 
    { 
     _myFilterMethodExtension = TheMethodExtension; 
     _directories = Directories; 

     initializeFileInfoList(); 
    } 

    ... 

    /// <summary> 
    /// Initializes the Files list. 
    /// </summary> 
    private void initializeFileInfoList() 
    { 
    ... 
     for (int i = 0; i < _directories.Count; i++) 
     { 
      iEnumerableFileInfo = new[] { _directories[i] }.Traverse(dir => 
      getDirectoryInfosWithoutThrowing(dir)).SelectMany(dir => 
      getFileInfosWithoutThrowing(dir)._myFilterMethodExtension()); 
+1

http://stackoverflow.com/questions/1016033/extension-methods-defined-on-value-types-cannot-be-used-to-create-delegates-wh – AlexanderBrevig 2014-09-19 22:58:49

+0

@AlexanderBrevig你能帮助我了解问题/答案的哪一部分是我的外卖?显然我不够聪明,看不到连接。 – 2014-09-19 23:00:54

+0

你不能这样做,因为静态方法调用是在编译时编译的。解释你的实际目标是什么可能有助于找到好看的方法(比如使用服务定位器模式来实现的扩展方法)。 – 2014-09-19 23:15:15

回答

3

如何将扩展方法作为参数传递给类的构造函数?

使参数成为与您正在查找的签名匹配的委托。例如,Func<IEnumerable<FileInfo>, IEnumerable<FileInfo>>将适用于您提供的情况。

public MainFileInfoSource(List<DirectoryInfo> Directories, 
      Func<IEnumerable<FileInfo>, IEnumerable<FileInfo>> FilterMethod) 

注意,在这种情况下,你将不得不使用它的静态位置,或者使用lambda表达式识别方法:

var source = new MainFileInfoSource(directories, FileFilterExtensions.IsAwesome); 
var source2 = new MainFileInfoSource(directories, f => f.IsAwesome()); 

...,并在该类方法使用该扩展名作为扩展名?

这是无法完成的。扩展方法只是特殊的语法糖,并且有很多关于如何使用它们的规则。从扩展方法创建委托时,此信息不会传输。所以你必须调用委托作为一个常规方法。

 iEnumerableFileInfo = new[] { _directories[i] } 
      .Traverse(dir => getDirectoryInfosWithoutThrowing(dir)) 
      .SelectMany(dir => _myFilterMethod(getFileInfosWithoutThrowing(dir))); 
+0

谢谢。这应该工作。我真的想把它表示为一个IEnumerable方法的扩展,这使我对任何其他方法失明。太糟糕了,但我喜欢叠加方法扩展。:-) – 2014-09-19 23:28:21

+0

我想我也可以编写一个“泛型”IEnumerable过滤器扩展方法,将过滤器字符串作为参数,并将该过滤器字符串也传递给我的构造函数。如果我真的想强制扩展方法。 – 2014-09-19 23:30:32

0

不为你工作?

public class MainFileInfoSource 
{ 
    public MainFileInfoSource(List<DirectoryInfo> Directories, 
     Func<IEnumerable<FileInfo>, IEnumerable<FileInfo>> TheMethodExtension) 
    { 

    } 
} 

new MainFileInfoSource(null, IEnumerableMethodExtensions.IsImageFile); 

+0

瓦伦丁,我实际上无法弄清楚如何让getFileInfosWithoutThrowing()中的点(通过Intellisense)出现方法扩展。我认为Alexander和StriplingWarrior已经向我澄清说,C#不希望我尝试将代表作为方法扩展来表达。 – 2014-09-19 23:24:51