如何将扩展方法添加到许多类

本文关键字:添加 许多类 方法 扩展 | 更新日期: 2023-09-27 17:57:32

我有大约 1000 个类,我需要计算其中的属性数量。我有以下代码:

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

我可以将其复制并粘贴到更改 typeof 参数的每个类中,但这似乎有点乏味。

无论如何可以通过执行var nop = C507.NumberOfProperties();来制作扩展方法来执行此操作?

如何将扩展方法添加到许多类

只是为了补充答案,建议为完整性object扩展: 您还可以考虑仅为Type实现扩展:

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

并像这样使用它:

typeof(C507).GetPropertyCount();

优点是可以直接从类型中获取属性数,而不必先创建实例。

因此,您可以编写使用对象的扩展方法或使用类型的扩展方法。

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 个类或复制和粘贴 1000 次typeof()

在这种情况下,您将需要从大会中阅读所有内容。

所以像这样:

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 实例化它(如果它具有无参数构造器(。您还可以使用反射自动填充属性。

不可能

像你想象的那样有一个静态扩展方法。话虽如此,可以在帮助程序类中创建泛型方法,如下所示。

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

给定一个类型SomeType它可以称为 int n = NumberOfProperties<SomeType>()

您可以在object上创建一个扩展方法,如下所示:

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

并在您喜欢的任何对象上使用它:

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

如果你想在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(); 

如果你想在Type上有一个extesnion方法:

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

几种方法可以做到这一点,它们是同一事物的变体。

可以将 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));

使用 C# 中的泛型系统使语法更简洁一些。那看起来像这样:

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。在此线程中查看他的答案:https://stackoverflow.com/a/38455233/984780

您可以创建一个适用于所有类型的通用扩展方法:

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

这将适用于所有类型,包括适用于对象的值类型(即结构(。感谢 piedar 在这里指出我的错误,应用于对象仍然将此扩展方法添加到值类型中。

如果分类可以实现接口,则可以扩展该接口。

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

话虽如此,拥有数百个(生成的?(类看起来是一个糟糕的解决方案。