以前发过一贴,http://bbs.csdn.net/topics/390232441
不过感觉没有得到很好的解答,再问一次,比如有两个类:
class A{
}
class B{
   public static A createA();
}
类A不能直接实例化,如  A a = new A(); 禁止象上面直接实例化,
而必须通过B的方法来创建A,如:   A a = B.createA();
就是说:
  A a = new A();  //不允许这样直接实例化
  A a = B.createA();  //只能通过B来创建A我这样做是有用途的,
因为A是通过代码生成器生成的,生成之后,A就不能再改了,
如果要改,只能通过B来改,比如B创建A对象,并初始化A的一些属性,也许我的思路不对,不知道大家有没有更好的解决方法?
比如我生成数据对象的增删改查方法,生成后就不能手工去改它,
只能通过代码生成器重新生成。
但如果生成的代码不满足业务,需要增加功能时,我就通过B类来扩展A的功能,然后调用A时,必须通过B来创建A,避免不经过B的初始化就调用A.
这个非常类似于工厂模式,但工厂模式通过反射,我又不想反射,反射影响效率,而且代码难写

解决方案 »

  1.   

    主要是想问一下,如何实现这样的功能,
    A类是自动生成的,不能手工去改,
    如果要扩展功能,只能通过别的方式去扩展,
    而且外面要调用A,必须是扩展之后的A。
      

  2.   

    使用私有构造函数
    class A
    {
        private A() {}
    }
    或者使用静态类
    static class
    {
        ...
    }
    还有抽象类:
    abstract class A
    {
        ...
    }
      

  3.   

    你可以把A实现成接口或者抽象类,这样A就不能实例化,外面使用A必须使用他的子类,在子类中实现或者扩展A的功能
      

  4.   


    abstract class A //抽象类不能实例化
    {
    }
    class B :  A  //在B中可以重写和修改A的方法满足自己的需求
    {
       public static A createA() { return (A)new B(); }//返回A类型 但是是B的实现
    }不知道这样能不能满足你的需求!
    “但如果生成的代码不满足业务,需要增加功能时,我就通过B类来扩展A的功能” 这句我不是很理解!
    如果你的意思是给B增加方法 使用的时候是通过B来调用这没问题
    但是如果你是通过给B增加方法,最终A来调用这个就有问题了!  
    除非使用扩展方法来实现 但是不优美 如果多了会使方法管理和逻辑很混乱
      

  5.   

    public class A{
        private  A{
    }}设置成私有的,看看这样应该没法在别的地方实例化它。
      

  6.   


    如果A不能修改,那你无法阻止new A()这种。
      

  7.   

    供楼主参考DataRow 构造函数protected internal DataRow(
    DataRowBuilder builder
    )
      

  8.   

    将A类定义为抽象类最适合。
    public abstract class A
    {
    }
      

  9.   

    代码生成应该以程序为核心,可以通过class创建或修改表格,不应该通过表格生成class。
      

  10.   

    如果一定要这样做,#4有答案,用继承。那就没必要CreateA了,直接使用B
      

  11.   

    楼主,你可以看一下这个类,
    .net自带的,DataRow这个类。
    DataRow的情况,和你描述的完全一致。
    不能直接实例化,
    只能通过DataTable.NewRow()来创建一个新的实例。通过参考DataRow类的语法,
    还有相关类的,比如DataTable之类的相互关系,
    能帮你更好的完善这一块的应用。
      

  12.   

    用 工厂被 。1.Assembly.GetXXXXXXXXXX.CreateInstence();2.Activator.CreateInstance();2个都可以,
      

  13.   


    回四楼,举个例子,A类提供几个属性:
      private FldName as string
      private FldSize as string
      private isemail as string
      private rule as string其中的 FldName 和 FldSize 的值是通过代码生成器生成的,
    而 isemail 和 rule 没办法生成,只能通过一个 B 类来初始化A,
    就是 B 类会扩展 A 类的属性和方法,
    然后创建A的实例,必须通过 B 来创建.
    A不允许直接创建,如果直接创建A,那 isemail 和 size 就会没被初始化,不合要求.
    很类似于15楼说的,DataRow 的结构是根据 DataTable的结构 复制而来,15楼说的,DataRow 是怎么实现的?
      

  14.   

    最好不要使用反射,反射影响效率,而且外面也可以通过反射直接实例化,
    通过抽象也算是一种方法,但抽象还必须提供一个继承类,比较麻烦,不过也算是一种比较合理的方式,
    DataRow 是如何实现的?谁能说一下,我也好了解下看是不是符合要求,
      

  15.   

    还有,两个类必须是分在不同的文件,
    A类一个文件,B类一个文件,不知道part 修饰符可以实现不?我看IDE自动生成的界面和后台代码,都有 partial 修饰符,
    IDE自动生成的代码,一般是不允许改的,而后台代码可以随意改,
    和这个有点类似,
      

  16.   

    abstract class A //抽象类不能实例化
    {
    protected FldName as string
    protected FldSize as string
    }
    class B :  A
    {
    protected isemail as string
    protected rule as string
    }
    直接用B替代A不行吗?为什么要CreateA?
      

  17.   

    把A的构造函数声明为private,再写一个static函数来创建A的实例
    class A
    {
        private A(){}
        private static A a = null;
        public static A GetA(){
            if(A == null)
                a = new A();
            return a;
       }
    }
      

  18.   

    禁止对象直接实例化这个问题很简单。
    首先  要实例化对象就必须得调用构造函数。
    要想不能直接实例化,可以把构造函数私有化,如private Singleton(){}然后对外公开一个方法来创建对象 如  public static Singleton GetInstance(){.......}
    //最简单的单例
    public class Singleton
    {        
        private static Singleton instance;        
        private Singleton(){}        
        public static Singleton GetInstance()        
        {                
           if(instance==null)                
           {                        
              instance=new Singleton();                
           }                
           return instance;        
        }
    }
      

  19.   

    回22楼,这个B类属于一种加工性质的类,用来加工A类的,而不是替代A类,
    如果B继承A,那就变成替代了,替代很明显不合要求,
    因为我可以由B来加工A类,也可以由C来加工A类,这个是很自由的,
    但如果用继承,就必须得继承A所有的方法和属性,就会造成一个庞大的B类,而且B不仅可以加工A类,还可以加工A1类、A2类...如同工厂的一条生产线,可以生产不同的产品一样...所以不能使用继承。没有哪个工厂会让一条生产线继承一种产品。
      

  20.   

    因为你前面从来就没有提到过“加工”,反而一再重复“扩展”,那么继承应该是最好的方法了。
    B继承A,C也继承A有什么关系呢?B类很大有什么关系呢?
    否则你得手工包装,重写所有需要的方法与属性,何必呢?如果你需要的是“加工”,那么针对的应该是接口,而不是类。
      

  21.   

    而且加工的话,更不应该有CreateA这种东西。你应该先new出实例了,才能送去加工。
      

  22.   


    .net框架这些东西都是开源的,而且也有类似Reflector等工具,你可应该自己看。
      

  23.   

    接口相当于图纸,只能作为参照,
    但工厂不能直接拿图纸来生产,必须有实物才行,
    A类就是一个实物,而不是接口,
    B类这个工厂类,生产出A对象,
    这个不能用继承,因为B类不仅生产A对象,还可能生产A1、A2、A3、等很多种类的对象,
    难道都要继承这些类才行?
      

  24.   

    类的可访问性 public改为private就可以了。 
      

  25.   

    我现在真不知道你到底要个什么东西了?工厂?但是看你#17的描述貌似还不是普通的工厂,还要能再包装?
    如果要个普通的工厂,要么用反射,要么自己写case。
    如果要能对任意类真实扩展,也许只能用动态类型dynamic。
      

  26.   


    A的构造函数为protected这样不能直接实例化A,但子类中可进行A的实例化。
    然后B继承A,createA中生成一个A的对象
    代码如下
    public class A
    {
    protected A(){}
    }
    public class B:A
    {        
    public B(){}
    public A createA()
    {
    return new A();
    }
    }
      

  27.   

    怎么不考虑用类的partial修饰符呢?
      

  28.   

    楼主可以看看设计模式之Proxy代理模式
      

  29.   

    1、用接口或抽象不太可能,因为LZ想自动生成类A的代码。
    2、用普通的继承也不太可能,
       如果类B中的方法返回类A的实例的话,那么类A的访问级别不可能小于类B的访问级别,
       也就是B是public,A也必须是public的。

    3、除了类B,如果类A不能被其它类直接实例化的话,又要保证2可以实现,
       可以将类A的构造函数声明成受保护的,类B继承类A。
       但是在类的CreateA函数中只能写“return (A)new B();”,不能写“return new A();”。
      

  30.   


    B属于一种加工性质的类,不能继承A,因为它不仅能生成A,也可能生成C,生成D...
    如果用继承,那就都得继承这些类,很明显是不行的,而且C#也不支持多继承,
      

  31.   

    B类是专门用来扩展A类的,
    扩展A类的一些属性和方法,以及实例化A类,
      

  32.   

    Proxy代理模式?代理模式不能返回调用的类吧,而是返回代理类,
    B类相当于代理类,而A类相当于真正处理的类,但代理模式,不能返回A的实例,而是返回B类的实例,通过B类去调用A类的方法.我要求的是,A和B类没有任何耦合的,不能用继承,继承的话A和B就耦合在一起了,
    也不能用代理,代理时,A类被封装在内部,外面无法直接得到A的实例,其实只是控制A类的 创建,要B来创建,创建后,A对象和B就没有任何关系了。
      

  33.   

    其实你需要和C++的友元类差不多,唯一的一点区别是你希望B认识A,而A不认识B,而友元类需要A认识B。然后咱总结一下你的逻辑,A要事先存在,B认识了A,然后B成为了A的友元类,但是A不能更改的话A还是不认识B。也就是说B->A的关系是单向的,那也就是说,你可以有B->A的关系,那我也可以做一个C->A或者D->A的关系,你B->A是怎么实现的,那我也可以同样的去做。也就是说,你自己的逻辑本身就存在矛盾。
      

  34.   

    B 继承A 把A的方法重写好了。问题:看不出你提出这个需求有啥意义。
      

  35.   


    有意义啊,我的A类是通过代码生成器生成的,不能手工去改,
    所以我另外建了一个B类,去改A类,然后外界要得到A的实例,必须是B改过后的实例。这个有点类似于设计模式里的 装饰模式,
    B来装饰 A
      

  36.   

    而且A类和B类必须分开存放,
    因为我用代码生成器重新生成A后,直接就覆盖原来的文件,
    所以要求A类不能有任何手工改动的代码,如果手工改动,下次重新生成,就会把改动的全部给覆盖了。所以我要求A是一个单独的文件,而B是另外一个文件,
    B来装饰A类,或者叫修改A类,很奇怪,这是非常合理的要求,怎么就没人碰到过类似的呢?
      

  37.   

        class A
        {
            protected A() { }
        }    class B
        {
            private class A1 : A { }        private class A2 : A { }        public static A CreateA(int n)
            {
                switch (n)
                {
                    case 1:
                        return (A)new A1();
                    case 2:
                        return (A)new A2();
                }
                return null;
            }
        }
      

  38.   

    B类不仅生产A对象,还可能生产A1、A2、A3、等很多种类的对象 
    这样的话,A,A1,A2必须都实现一个相同的接口,否则,当你把A改为A1的时候,以前使用A定义的引用就都需要修改成A1,所以必须暴露给外面一个接口。这样如果希望把A,A1,A2作为装饰模式来使用的话就比较容易了。
     
    return new A(new A1(new A2())); 
    1.interface MyInterface{  
    2.    public void sayHello();  
    3.      
    4.}  
    5.  
    6.class A implements MyInterface{  
    7.          
    8.    public void sayHello(){  
    9.        System.out.println("hello A");  
    10.    }     
    11.}  
    12.  
    13.class A1 implements MyInterface{  
    14.          
    15.    public void sayHello(){  
    16.        System.out.println("hello A1");  
    17.    }     
    18.}  
    19.      
    20.class A2 implements MyInterface{  
    21.          
    22.    public void sayHello(){  
    23.        System.out.println("hello A2");  
    24.    }     
    25.}  
    26.  
    27.class B{  
    28.    public static MyInterface createA(){  
    29.        return new A();  
    30.    }  
    31.}  
    32.  
    33.public class MyTest  
    34.{  
    35.    public static void main(String[] args)  
    36.    {  
    37.        MyInterface a = B.createA();  
    38.        a.sayHello();  
    39.    }  
    40.}  
      

  39.   

    而且A类和B类必须分开存放,
    因为我用代码生成器重新生成A后,直接就覆盖原来的文件,
    所以要求A类不能有任何手工改动的代码,如果手工改动,下次重新生成,就会把改动的全部给覆盖了。
      

  40.   

    >>代码生成器,或多或少会遇到这个问题。 如果只需要保留自己写的代码。 楼主有点误导大家了。 在vs2008中将自己写的代码类在新类中以 部分类 定义就行。
     public partial class A {
    }