Подтвердить что ты не робот

Как добавить метод расширения для многих классов?

У меня около 1000 классов, в которых мне нужно подсчитать количество свойств. У меня есть следующий код:

    public static int NumberOfProperties()
    {
        Type type = typeof(C507);
        return type.GetProperties().Count();
    }

Я мог бы скопировать и вставить это в каждый класс, изменив параметр typeof, но это кажется немного утомительным.

В любом случае, чтобы сделать метод расширения, просто сделав var nop = C507.NumberOfProperties();?

4b9b3361

Ответ 1

Невозможно иметь статический метод расширения, как вы себе это представляете. При этом можно было бы создать общий метод в вспомогательном классе следующим образом.

public static int NumberOfProperties<T>()
{
    Type type = typeof(T);
    return type.GetProperties().Count();
}

Для типа SomeType его можно назвать int n = NumberOfProperties<SomeType>().

Ответ 2

Чтобы добавить к ответам, предлагающим расширение для object для полноты: вы также можете рассмотреть возможность внедрения расширения только для Type:

public static int GetPropertyCount(this Type t)
{
    return t.GetProperties().Length;
}

и используйте его следующим образом:

typeof(C507).GetPropertyCount();

Преимущество состоит в том, что вы можете получить количество свойств непосредственно из этого типа и не создавать экземпляр сначала.

Ответ 3

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

public static class ObjectExtensions
{
    public static int GetNumberOfProperties(this object value)
    {
        return value.GetType().GetProperties().Count();
    }

    public static int GetNumberOfProperties(this Type value)
    {
        return value.GetProperties().Count();
    }
}

Использование:

new C507().GetNumberOfProperties();
typeof(C507).GetNumberOfProperties();

Однако вы явно указываете две вещи:

Я мог бы скопировать и вставить это в каждый класс, изменив тип

У меня около 1000 классов

Вероятно, вы не захотите создать экземпляр 1000 классов или скопировать и вставить typeof() 1000 раз

В этом случае вы захотите прочитать их все из сборки.

Так что-то вроде:

typeof(SomeClass).Assembly.GetTypes().Select(x => new
  {
       x.Name, 
       PropertyCount = x.GetType().GetProperties().Count()
  });

Где SomeClass - класс (не имеет значения, где), где все классы находятся.

Я просто выбираю их в анонимный объект, который содержит имя и количество типов.

Это:

typeof(SomeClass).Assembly

Это просто способ убедить собраться. Существуют и другие способы.

Assembly.GetAssembly(typeof(Program)).GetTypes()
Assembly.GetCallingAssembly().GetTypes()
Assembly.Load("Some Assemble Ref").GetTypes()

Вы можете делать все сортировки с типами, которые вы найдете. Если вы выберете сам Type, вы можете создать его позже, используя Activator.CreateInstance (если у него есть без параметров constuctor). Вы также можете автоматически заполнять свойства отражением.

Ответ 4

Вы можете сделать метод расширения на object следующим образом:

public static int PropertyCount(this object thing)
{
    return thing.GetType().GetProperties().Count();
}

И используйте его для любого объекта, который вам нравится:

var x = "some string";
var numProps = x.PropertyCount();

Ответ 5

Если вы хотите иметь метод расширения на object:

public static ObjectExtensions
{
    public static int NumberOfProperties(this object value)
    {
        if (null == value)
          throw new ArgumentNullException("value"); // or return 0

        // Length: no need in Linq here
        return value.GetType().GetProperties().Length;
    }
}

...

C507 myObj = new C507();

// How many properties does myObj instance have?
int propCount = myObj.NumberOfProperties(); 

Если вы хотите использовать метод extesnion для Type:

   public static TypeExtensions
    {
        public static int NumberOfProperties(this Type value)
        {
            if (null == value)
              throw new ArgumentNullException("value"); // or return 0

            // Length: no need in Linq here
            return value.GetProperties().Length;
        }
    }

    ...


    // How many properties does C507 type have?
    int propCount = typeof(C507).NumberOfProperties(); 

Ответ 6

Есть несколько способов сделать это, которые являются вариациями одного и того же.

Вы можете передать Type в качестве аргумента методу:

public static class Helper {
    public static int NumberOfProperties(Type type)
    {
        return type.GetProperties().Count();
    }
}

Что вы бы назвали так:

// Imagine you have a class called MyClass
var result = Helper.NumberOfProperties(typeof(MyClass));

Вы используете использование общей системы в С#, чтобы сделать синтаксис немного чище. Это будет выглядеть так:

public static class Helper {
    // Notice the argument was removed and 
    // the use of the "generic" syntax <T>
    public static int NumberOfProperties<T>()
    {
        var type = typeof(T);
        return type.GetProperties().Count();
    }
}

И вы бы назвали это следующим образом:

var result = Helper.NumberOfProperties<MyClass>();

Вы также можете использовать "Расширения", которые позволяют вызывать его так, как если бы это был метод, принадлежащий вашим классам.

public static class Helper {
    // notice the `this` keyword before the parameter 
    // this is what tells C# that this is an extension method
    public static int NumberOfProperties<T>(this T @this)
    {
        var type = typeof(T);
        return type.GetProperties().Count();
    }
}

Это позволит вам вызвать метод следующим образом:

 var instance = new MyClass();
 var result = instance.NumberOfProperties();

В этом примере я использовал общий синтаксис, чтобы он применялся к любому типу объекта. Если вы хотите ограничить его только объектами, которые наследуются от определенного интерфейса или базового класса, вы просто измените его на использование общего синтаксиса на использование базового класса/интерфейса. Вот так:

public static class Helper {
    // notice the type got changed from a generic <T>
    // to specifying the exact class you want to "extend"
    public static int NumberOfProperties(this MyBaseClass @this)
    {
        var type = typeof(T);
        return type.GetProperties().Count();
    }
}

Как упоминалось в @rené-vogt, вы также можете создать метод расширения, чтобы вместо него расширять тип Type. Посмотрите его ответ в этой теме: fooobar.com/questions/211910/...

Ответ 7

Вы можете создать общий метод расширения, который может применяться ко всем типам:

public static int PropertyCount<T>(this T obj)
{
    return typeof(T).GetProperties().Length;
}

Это применимо ко всем типам, включая типы значений (IE structs), которые не применяются к объекту. Благодаря piedar для указывая на мою ошибку здесь, применение к объекту все равно добавляет этот метод расширения к значениям типов.

Ответ 8

Если ваш класс может реализовать интерфейс, вы можете расширить этот интерфейс.

public interface IExtensible {
}

class C507 : IExtensible {

}

public static int NumberOfProperties(this IExtensible extensible)
{
    Type type = extensible.GetType();
    return type.GetProperties().Count();
}

Говоря, что сотни (сгенерированных?) классов выглядят как плохое решение для начала.