Могу ли я добавить методы расширения в существующий статический класс? - PullRequest
490 голосов
/ 30 октября 2008

Я фанат методов расширения в C #, но не смог успешно добавить метод расширения в статический класс, такой как Console.

Например, если я хочу добавить в консоль расширение, называемое «WriteBlueLine», чтобы я мог перейти:

Console.WriteBlueLine("This text is blue");

Я попробовал это, добавив локальный, публичный статический метод, с консолью в качестве параметра 'this' ... но без кубиков!

public static class Helpers {
    public static void WriteBlueLine(this Console c, string text)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine(text);
        Console.ResetColor();
    }
}

Это не добавило метод 'WriteBlueLine' в Консоль ... я делаю это неправильно? Или просить невозможного?

Ответы [ 15 ]

1 голос
/ 12 августа 2018

Невозможно написать метод расширения, однако возможно имитировать запрашиваемое вами поведение.

using FooConsole = System.Console;

public static class Console
{
    public static void WriteBlueLine(string text)
    {
        FooConsole.ForegroundColor = ConsoleColor.Blue;
        FooConsole.WriteLine(text);
        FooConsole.ResetColor();
    }
}

Это позволит вам вызывать Console.WriteBlueLine (fooText) в других классах. Если другие классы хотят получить доступ к другим статическим функциям Консоли, на них нужно будет явно ссылаться через их пространство имен.

Вы всегда можете добавить все методы в класс замещения, если хотите, чтобы все они были в одном месте.

Так что у вас будет что-то вроде

using FooConsole = System.Console;

public static class Console
{
    public static void WriteBlueLine(string text)
    {
        FooConsole.ForegroundColor = ConsoleColor.Blue;
        FooConsole.WriteLine(text);
        FooConsole.ResetColor();
    }
    public static void WriteLine(string text)
    {
        FooConsole.WriteLine(text);
    }
...etc.
}

Это обеспечит то поведение, которое вы ищете.

* Примечание. Консоль необходимо будет добавить через пространство имен, в которое вы ее поместили.

1 голос
/ 21 ноября 2015

Следующее отклонено как edit к ответу tvanfosson. Меня попросили внести это как мой собственный ответ. Я воспользовался его предложением и закончил реализацию оболочки ConfigurationManager. В принципе, я просто заполнил ... в ответе tvanfosson.

Нет. Методы расширения требуют экземпляра объекта. Вы можете однако, напишите статическую оболочку вокруг ConfigurationManager интерфейс. Если вы реализуете обертку, вам не нужно расширение метод, так как вы можете просто добавить метод напрямую.

public static class ConfigurationManagerWrapper
{
    public static NameValueCollection AppSettings
    {
        get { return ConfigurationManager.AppSettings; }
    }

    public static ConnectionStringSettingsCollection ConnectionStrings
    {
        get { return ConfigurationManager.ConnectionStrings; }
    }

    public static object GetSection(string sectionName)
    {
        return ConfigurationManager.GetSection(sectionName);
    }

    public static Configuration OpenExeConfiguration(string exePath)
    {
        return ConfigurationManager.OpenExeConfiguration(exePath);
    }

    public static Configuration OpenMachineConfiguration()
    {
        return ConfigurationManager.OpenMachineConfiguration();
    }

    public static Configuration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap, ConfigurationUserLevel userLevel)
    {
        return ConfigurationManager.OpenMappedExeConfiguration(fileMap, userLevel);
    }

    public static Configuration OpenMappedMachineConfiguration(ConfigurationFileMap fileMap)
    {
        return ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
    }

    public static void RefreshSection(string sectionName)
    {
        ConfigurationManager.RefreshSection(sectionName);
    }
}
1 голос
/ 09 ноября 2014

да, в ограниченном смысле.

public class DataSet : System.Data.DataSet
{
    public static void SpecialMethod() { }
}

Это работает, но Консоль - нет, потому что она статическая.

public static class Console
{       
    public static void WriteLine(String x)
    { System.Console.WriteLine(x); }

    public static void WriteBlueLine(String x)
    {
        System.Console.ForegroundColor = ConsoleColor.Blue;
        System.Console.Write(.x);           
    }
}

Это работает, потому что пока оно не в том же пространстве имен. Проблема в том, что вы должны написать статический метод прокси для каждого метода, который есть в System.Console. Это не обязательно плохо, так как вы можете добавить что-то вроде этого:

    public static void WriteLine(String x)
    { System.Console.WriteLine(x.Replace("Fck","****")); }

или

 public static void WriteLine(String x)
    {
        System.Console.ForegroundColor = ConsoleColor.Blue;
        System.Console.WriteLine(x); 
    }

Способ работает так, что вы подключаете что-то к стандартному WriteLine. Это может быть счетчик строк или фильтр плохих слов или что-то еще. Всякий раз, когда вы просто указываете Консоль в своем пространстве имен, скажем, WebProject1 и импортируете пространство имен System, WebProject1.Console будет выбираться вместо System.Console по умолчанию для этих классов в пространстве имен WebProject1. Так что этот код превратит все вызовы Console.WriteLine в синий, поскольку вы никогда не указывали System.Console.WriteLine.

0 голосов
/ 29 мая 2017

Вы можете использовать приведение к null, чтобы заставить его работать.

public static class YoutTypeExtensionExample
{
    public static void Example()
    {
        ((YourType)null).ExtensionMethod();
    }
}

Расширение:

public static class YourTypeExtension
{
    public static void ExtensionMethod(this YourType x) { }
}

YourType:

public class YourType { }
0 голосов
/ 15 сентября 2010

Вы МОЖЕТЕ сделать это, если вы хотите немного «заморозить» его, создав переменную статического класса и присвоив ей значение null. Однако этот метод не будет доступен для статических вызовов класса, поэтому не уверен, насколько он будет полезен:

Console myConsole = null;
myConsole.WriteBlueLine("my blue line");

public static class Helpers {
    public static void WriteBlueLine(this Console c, string text)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine(text);
        Console.ResetColor();
    }
}
...