可能的通用暴露包含类

本文关键字:暴露 包含类 | 更新日期: 2023-09-27 18:02:23

假设我有一些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的子类:

cls.SubFunctions<MyClass1>().Hello() & lt; & lt;只显示Base.MySubClass,不显示MyClass1.MySubClass1

有没有办法做到这一点,而不传递MyClass1.MySubClass作为T ?

可能的通用暴露包含类

你考虑过这个问题吗?

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

你可以这样做:

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

你会注意到你的"子类"类的嵌套性质在这里没有关系。它们可以很容易地位于其他类之外。

但是如果我调用这个,它显然只会返回Base内部的函数。MySubClass而不是传递给它的T的子类:

您通常会通过接口来实现。如果你想传递任何实现了一组特殊特性的通用对象,而你只想访问这些特性,那么这就是接口的作用。无论底层类型如何,您都定义了可用的特定特性集合

  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实现提供者接口:

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

    毕竟,你一直在问如何在不包括任何基类实现的情况下抽象功能…接口非常适合抽象跨不相关类的公共功能

    并不妨碍你在相关的类型中使用它们;)

    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";}
        }
    }
    

最终的结果是,当你调用SubFunctions();返回的对象类型是INotBaseClassFunctions,因此在本例中没有强类型访问Hello()

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