【问题标题】:Access property of generic class泛型类的访问属性
【发布时间】:2018-07-02 22:07:37
【问题描述】:

我有一个扩展 BaseModel 类的模型类。

public abstract class BaseModel {
   public abstract string Name;
   public abstract string NamePlural;
   //....
}

public class Production : BaseModel
{
   public string Name = "production";
   public string NamePlural = "productions";
   //....
}

我在其他地方调用了另一个使用 BaseModel 作为泛型基础的类:

public class Store {
    public BaseModel SomeMethod<T>()
        where T : BaseModel
    {
         // here I need to get the Name property and the NamePlural property
         T.NamePlural; // gives compile error "T Not valid in the given context

         // next try:
         var model = typeof(T);
         model.NamePlural; // simply doesn't exist (model.Name gives the name of the class, but not the property)

         // another strange try:
         BaseModel model = new T(); // haha....nope

         //....
         return something...;
    }
}

//usage:

Store store = new Store();
Production p = SomeMethod<Production>();

所以问题是
有没有一种简单的方法可以访问这些属性?
我什至尝试通过Assembly.GetTypes()..., ...

或者我需要 another 这些答案中描述的流派类: How to access Property of generic member in generic class?

是的,我已阅读相关问题 Access to properties of generic objectGet property of generic class

【问题讨论】:

  • “获取 Name 属性”是什么意思 - 您是指 PropertyInfo 反射元数据吗?有没有对象实例传入方法? ...
  • “获取NamePlural 属性”到底是什么意思?你需要用它做什么?
  • 1) 你的子类属性不是override,所以它没有按照你的想法做。 2) NameNamePlural 应该是静态的吗?你没有对象可以工作,所以很混乱。请创建一个minimal reproducible example
  • 假设你的代码不需要是泛型的,你会怎么写呢?正如另一条评论中提到的,您要在其上调用方法的类型 T 的对象在哪里?
  • 字段不能是抽象的。 T 是一个类型,而不是一个对象。您需要一个对象来访问非静态成员。

标签: c# generics


【解决方案1】:

基础模型应该有属性,而不是字段。

public abstract class BaseModel {
   public abstract string Name { get; }
   public abstract string NamePlural { get; }
   //....
}

你必须重写抽象方法来实现它们。

public class Production : BaseModel
{
   public override string Name => "production";
   // Same as:  public override string Name { get { return "production"; } }

   public override string NamePlural => "productions";
   //....
}

将对象传递给SomeMethod

public class Store {
    public BaseModel SomeMethod<T>(T model)
        where T : BaseModel
    {
        string name = model.Name;
        string namePlural = model.NamePlural;
        ...
    }
}

仅访问名称,不需要泛型类型参数,因为Production 和其他派生类继承了名称。您仍然可以将生产对象作为参数传递给该方法:

public class Store {
    public BaseModel SomeMethod(BaseModel model)
    {
        string name = model.Name;
        string namePlural = model.NamePlural;
        ...
    }
}

如果您想在泛型类型参数上使用new,请添加new 约束。这会强制类型 T 具有默认构造函数,即没有参数的构造函数:

public BaseModel SomeMethod<T>()
    where T : BaseModel, new
{
    var model = new T();
    string name = model.Name;
    ...
}

如果你想给Production 一个静态行为,你可以让它成为一个单例。在类型名称或泛型类型名称上,您只能访问静态成员。由于静态成员不能是抽象的,也不能被继承,如果你想要继承和静态行为,单例模式是一种选择。

public class Production : BaseModel
{
    public static readonly Production Instance = new Production();

    private Production() // makes it non-instantiatable form outside.
    { }

    ...
}

你会这样使用

store.SomeMethod(Production.Instance);

【讨论】:

  • 非常感谢各种解决方案和提示!
  • 虽然将Production 的对象传递给该方法实际上并没有什么意义——仅在逻辑上。直到那时它才存在。无论如何,我会根据您的提示找到方法。
  • 或者,如果您添加new 通用约束,您可以在方法中使用new T() 创建它。
猜你喜欢
  • 1970-01-01
  • 2019-03-08
  • 2011-09-24
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-03
相关资源
最近更新 更多