通用类的访问属性

时间:2018-07-02 22:07:38

标签: c# generics

我有一个Model-Class,它扩展了BaseModel-class。

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()..., ...

还是我需要这些答案中所述的另一个一般类: How to access Property of generic member in generic class吗?

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

1 个答案:

答案 0 :(得分:4)

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

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