【问题标题】:Create inherited class from type parameter从类型参数创建继承类
【发布时间】:2016-08-19 13:57:45
【问题描述】:

我有一个通用控制器,我将一个只包含属性的类传递给它。这一切都很好,但是......

我想在Controller类中创建另一个类来继承传递的类。

有点像这样:

public class Products
{
    public Int32 ProductID {get; set;}
    public String ProductName {get; set;}
}

public class ProductController : Controller<Products>
{
    public ProductsController() : base("Products", "ProductID", "table", "dbo")
    {
    }
}

public class Controller<T> : IDisposable where T : new()
{
    protected Controller(String tablename, String keyname, String entitytype, String tableschema = "dbo")
    {
        ...
    }

    //How do I create the Recordset class inheriting T
    public class Recordset : T   //<----This is what I don't know how to do
    {
        public Int32 myprop {get; set;}

        public void MoveNext()
        {
            //do stuff
        }
    }
}

如何使用继承的 T 创建类 Recordset?

【问题讨论】:

  • 您是否尝试过包括where T : class, new()?你不能继承结构。
  • @Chris:看看 Nuget 上的ImpromptuInterface,它可以动态创建新类型,就像其他类型一样;但你真的不想去那里。另见en.wikipedia.org/wiki/Composition_over_inheritance
  • 谢谢,贝林。就是这样。以为我以前做过,但是...下面的解决方案。

标签: c# class generics inheritance


【解决方案1】:

编译器won't let you do that(我确信错误信息告诉了你):

不能从“标识符”派生,因为它是一个类型参数
泛型类的基类或接口不能由类型参数指定。从特定的类或接口派生,或者从特定的泛型类派生,或者将未知类型包含为成员。

您可以使用组合而不是继承:

public class Controller<T> : IDisposable where T : new()
{
    public class RecordSet 
    {    
        private T Records;
    
        public RecordSet(T records)
        {
            Records = records;
        }        

        public void MoveNext()
        {
            // pass through to encapsulated instance
            Records.MoveNext();
        }            
    }
}

【讨论】:

  • 不,它是一个嵌套类,所以它可以“免费”获得它——它是一个Controller&lt;T&gt;.RecordSet
  • 啊,我以为 OP 刚刚弄乱了括号。
  • 不!没有支架问题! :)
  • 旁注:“不能”有点太强了 - 如果一个人真的想这样做,而不是通过一些 IL 生成它可以实现......但对于除了一小部分 C# 开发人员之外的任何人这真的超出了他们的专业知识/可能范围。
  • @Aron 您能否指出C# 规范中禁止 在运行时创建类型的部分? (我没有看到问题中对特定语法的严格要求 - 它显示的方式似乎非常紧凑,易于阅读对我的目标解释,但可能不是确切的语法/方法)
【解决方案2】:

您可以使用 Reflection.Emit 命名空间下的类来做到这一点。但如果你深入挖掘,你可能会发现你不需要继承。

【讨论】:

  • 想举个例子吗?谢谢!
  • 我同意这一点。TypeBulder、ExpressionTrees、Code DOM。但是,您可能还想为此研究“依赖注入”主题。
【解决方案3】:
public class Controller<T> : IDisposable where T : class, new()
{
    protected Controller(String tablename, String keyname, String entitytype, String tableschema = "dbo")
    {
        ...
    }
   public class Recordset<TT> where TT : class, new()   
    {
        public TT myinheritedclass {get; set}
        public Int32 myprop {get; set;}

        public void MoveNext()
        {
            //do stuff
        }
    }

    public Recordset<T> myRecordset = new Recordset<T>()
}

【讨论】:

  • 这是组合而不是继承。您将如何填充被映射类型的合同?使用 D.I. 你会更好。或发射。
  • 不。已经完美工作了 5 年。我现在已经使用这个结构数千次了,它完全按照我想要的方式工作。
猜你喜欢
  • 2011-02-21
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
相关资源
最近更新 更多