Generic Expose Contained Class可能吗?

时间:2014-05-09 01:38:38

标签: c# c#-4.0 generics

假设我有一堆类型为Base的类,如下所示:

public class MyClass1 : Base
{
    private MySubClass1 subClass1;
    public override Base.MySubClass subClass
    {
        get
        {
            return this.subClass1;
        }
        set
        {
            base.MySubClass = this.subClass1;
        }
    }
     public class MySubClass1 : Base.MySubClass
     {
         public string Hello1() {return "hello1";}    
     }
}

public abstract class Base
{
     public virtual MySubClass subClass {get;set;}
     public abstract class MySubClass
     {
         public string Hello() {return "hello";}
     }
}

我想知道的是,如果一般只能通过某种通用方法以流畅的API方式公开MySubClass1

我在想这样的事情:

public Base.MySubClass SubFunctions<T>() where T : Base, new()
{
   var x = new T();
   return x.subClass;
}

但是,如果我这称呼它,它显然只会返回Base.MySubClass内的函数而不是T的子类,我会传入它:

e.g。 cls.SubFunctions<MyClass1>().Hello()&lt;&lt;只会公开Base.MySubClass,而不是MyClass1.MySubClass1

有没有办法在不将MyClass1.MySubClass作为T传递的情况下实现此目的?

3 个答案:

答案 0 :(得分:1)

你考虑过这个吗?

public abstract class Base
{
     public virtual MySubClass subClass {get;set;}
     public abstract class MySubClass
     {
         public string Hello() {return "hello";}
     }

     public abstract MySubClass CreateSubClass();
}

答案 1 :(得分:1)

您可以这样做:

void Main()
{
    var hello = new MyClass1().subClass.Hello1();
}

public class MyClass1 : Base<MyClass1.MySubClass1>
{
    public override MySubClass1 subClass{get;set;}

    public class MySubClass1 : Base<MySubClass1>.MySubClass
    {
        public string Hello1() {return "hello1";}    
    }
}

public abstract class Base<T> where T : Base<T>.MySubClass, new()
{
    public Base() {subClass = new T();}
    public virtual T subClass {get;set;}
    public abstract class MySubClass
    {
        public string Hello() {return "hello";}
    }
}

不幸的是,这使得您尝试创建的方法更复杂一些:

public TSub SubFunctions<TBase, TSub>() 
    where TBase : Base<TSub>, new()
    where TSub : Base<TSub>.MySubClass, new()
{
    var x = new TBase();
    return x.subClass;
}

用法:

var hello = SubFunctions<MyClass1, MyClass1.MySubClass1>().Hello1();

您会注意到“子类”类的嵌套特性与此无关。它们可以很容易地位于其他类之外。

答案 2 :(得分:0)

  

但是如果我调用它,它显然只返回Base.MySubClass中的函数而不是T i的子类将传递给它:

您通常会通过界面执行此操作。 如果您想要的是传递任何实现一组特殊功能的通用对象,并且您只想访问这些功能,那么这正是接口的用途。您已定义特定可用功能集合的基础类型的注意事项

  1. 第一步是更改Base.MySubClass以实现您要公开的功能的界面

    public interface INotBaseClassFunctions
    {
        string SaySomethingElse();
    }
    
  2. 现在在MySubClass1中实现该接口

    public class MySubClass1 : Base.MySubClass, INotBaseClassFunctions
    {
        public override string SaySomethingElse() { return "Something Else :)"; }
    }
    
  3. 对于下一位,我认为你想要的是一种工厂/提供者模型。

      

    我想知道的是,如果一般只能通过某种通用方法以流畅的API方式公开MySubClass1

    你的问题“如何编写一个通用的方法,如果我指定一个类型,它会给我一个只暴露我的'更高级函数'的对象,而不是那个类型的其余功能”?

      

    对于不同的设计模式,这是一个很好的入门书:http://www.dofactory.com/Patterns/Patterns.aspx

         

    同时尝试使用http://msdn.microsoft.com/en-us/library/ee817667.aspx获取MSDN工厂模式,这是一个很好的阅读!

    这个简单的改变可能会起到作用:

    public INotBaseClassFunctionsProvider : Interface
    {
        INotBaseClassFunctions GetSubclass();
    } 
    
      

    注意:由您决定如何定义提供基础类型的方式,如果子类对象持久保存在提供程序对象中,我们通常只使用类中的属性,对于我喜欢使用方法的工厂和其他接口公开子类对象,因为我无法控制实际的实现,或者对象是否会被持久化。

         
        

    当您使用方法时,调用者必须推断获取对象本身就是一个可能需要时间或抛出错误的进程。

      
    public INotBaseClassFunctions SubFunctions<T>() where T : INotBaseClassFunctionsProvider, new()
    {
       var provider = new T();
       return provider.GetSubClass(); 
    }
    
  4. 所以把这一切放在一起,让MyClass1实现提供者接口:

      

    我把你的其他代码留在那里,但怀疑你现在会完全删除抽象关系。

         
        

    毕竟,你一直在问如何在不包含任何基类实现的情况下抽象功能......接口适用于 asbstracting 不相关类的通用功能

             
          

    不会阻止您在相关类型中使用它们;)

        
      
    public class MyClass1 : Base, INotBaseClassFunctionsProvider 
    {
        // base class implementation, note that this is not a good
        // coding practise, having a modifier that does not alter the output of the accessor
        // will likely cause headaches for someon down the track, make sure you 
        // document the reason why you have done this, if you ever do it.
        // Using interfaces we can remove the need to implement this base functionality altogether
        private MySubClass1 subClass1 = new MySubClass1();
        public override Base.MySubClass subClass
        {
            get
            {
                return this.subClass1;
            }
            set
            {
                base.MySubClass = this.subClass1;
            }
        }
    
        // INotBaseClassFunctionsProvider implementation
        public INotBaseClassFunctions GetSubclass()
        {
            return this.subClass1;
        }
    
        public class MySubClass1 : Base.MySubClass, INotBaseClassFunctions
        {
            public override string SaySomethingElse() { return "Something Else :)"; }
        }
    }
    
    public abstract class Base
    {
        public virtual MySubClass subClass { get; set; }
        public abstract class MySubClass
        {
            public string Hello() {return "hello";}
        }
    }
    
  5. 最终结果是当你调用SubFunctions()时; 你得到的对象是INotBaseClassFunctions类型,所以在这个例子中没有强类型访问Hello()

    我希望这在某种程度上有所帮助,而且我没有过多地误解你的要求:)