Как добавить метод расширения для многих классов?
У меня около 1000 классов, в которых мне нужно подсчитать количество свойств. У меня есть следующий код:
public static int NumberOfProperties()
{
Type type = typeof(C507);
return type.GetProperties().Count();
}
Я мог бы скопировать и вставить это в каждый класс, изменив параметр typeof
, но это кажется немного утомительным.
В любом случае, чтобы сделать метод расширения, просто сделав var nop = C507.NumberOfProperties();
?
Ответы
Ответ 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();
}
Говоря, что сотни (сгенерированных?) классов выглядят как плохое решение для начала.