将方法扩展作为参数传递

3

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

例如:这是一个包含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
https://dev59.com/1XNA5IYBdhLWcg3wUL5Y - AlexanderBrevig
@AlexanderBrevig,你能帮我理解那个问题/答案的哪一部分是我的收获吗?显然我不够聪明,看不出它们之间的联系。 - Cardinal Fang
你不能这样做,因为静态方法调用在编译时被编译。解释你的实际目标可能有助于找到好看的方法(例如使用服务定位器模式实现的扩展方法)。 - Alexei Levenkov
2个回答

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)));

谢谢。这应该可以工作。我真的想把它表达为一个IEnumerable方法扩展,这让我看不到其他方法。虽然很遗憾,我喜欢堆叠方法扩展。 :-) - Cardinal Fang
我想我也可以编写一个“通用”的IEnumerable过滤器扩展方法,该方法将过滤字符串作为参数,并将该过滤字符串传递到我的构造函数中。如果我真的想强制使用方法扩展。 - Cardinal Fang

0

对你不起,它对你不起作用吗?

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

    }
}

  new MainFileInfoSource(null, IEnumerableMethodExtensions.IsImageFile);

?


Valentin,我真的无法弄清楚如何在getFileInfosWithoutThrowing()(通过Intellisense)中让方法扩展显示在点之后。我认为Alexander和StriplingWarrior已经为我澄清了,C#不希望我尝试将委托表示为方法扩展。 - Cardinal Fang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接