C# 在运行时使用另一个基类更改/交换基类

C# 在运行时使用另一个基类更改/交换基类,c#,oop,class,C#,Oop,Class,听起来是个愚蠢的主意,但我想知道是否有可能 是否可以在运行时更改派生类的基类?当然,有很多如果和但是的问题,为什么会有人这样做,这可能是一个糟糕的设计和所有的 把所有这些放在一边(即使它们可能是完全正确的),比方说,只是为了好玩或是为了表现你的书呆子,有没有可能用C#或其他语言呢 比如: public class baseOriginal { public string justAProperty; } public class baseSwapped { public int

听起来是个愚蠢的主意,但我想知道是否有可能

是否可以在运行时更改派生类的基类?当然,有很多如果和但是的问题,为什么会有人这样做,这可能是一个糟糕的设计和所有的

把所有这些放在一边(即使它们可能是完全正确的),比方说,只是为了好玩或是为了表现你的书呆子,有没有可能用C#或其他语言呢

比如:

public class baseOriginal {
    public string justAProperty;
}

public class baseSwapped {
    public int sillyNumber;
}

public class derivedClass : baseOriginal {
   public bool iAmDumb;
}

void Main() {
    baseOriginal derived = new derivedClass ();
    Console.WriteLine(derived.justAProperty);
    baseSwapped derivedSwapped = (??);
    Console.WriteLine(derivedSwapped.sillyNumber);
}
这在C#中是不可能的。可能您更想要的是一种基于原型的解决方案,这种解决方案通常存在于动态语言(如JavaScript)中,您可以通过添加对象的定义方式来“扩展”对象的功能

但要完成代码提示的操作,可以让可交换类从公共祖先类继承。这样,您可以将每个的实例分配给它们的Decedent

public class baseClassAncestor{

}
public class baseOriginal:baseClassAncestor { 
    public string justAProperty; 
} 

public class baseSwapped:baseClassAncestor  { 
    public int sillyNumber; 
} 

public class derivedClass : baseOriginal { 
   public bool iAmDumb; 
} 
这在C#中是不可能的。可能您更想要的是一种基于原型的解决方案,这种解决方案通常存在于动态语言(如JavaScript)中,您可以通过添加对象的定义方式来“扩展”对象的功能

但要完成代码提示的操作,可以让可交换类从公共祖先类继承。这样,您可以将每个的实例分配给它们的Decedent

public class baseClassAncestor{

}
public class baseOriginal:baseClassAncestor { 
    public string justAProperty; 
} 

public class baseSwapped:baseClassAncestor  { 
    public int sillyNumber; 
} 

public class derivedClass : baseOriginal { 
   public bool iAmDumb; 
} 

您可以得到的最接近的结果是通过定义至少一个作为接口来派生这两种类型,然后将从一个派生到另一个。

您可以得到的最接近的结果是通过定义至少一个作为接口来派生这两种类型,然后从一个到另一个进行转换。

我能想到的最接近的事情是:

我不知道动态语言运行库是否可以做您希望它做的事情


你最接近的可能是 通过定义at从这两种类型派生 至少有一个作为接口,然后 从一个到另一个的铸造


我必须同意,基于这个例子,这个建议可以满足他想要做的,它也是一个比他实际想要做的更好的设计。

我能想到的最接近的事情是:

我不知道动态语言运行库是否可以做您希望它做的事情


你最接近的可能是 通过定义at从这两种类型派生 至少有一个作为接口,然后 从一个到另一个的铸造


我必须同意,基于这个示例,这个建议将满足他想要做的,它也是一个比他实际想要做的更好的设计。

您可以通过在使用派生类之前加载实现基类的不同程序集来进行一次性基类交换。但是这种方法不会使您的代码正常工作,因为您将无法编译这些代码,但是将对不同基类的方法的访问转移到单独的函数可能会正常工作

您可以添加包含所有基类中所有可能的方法/属性的UnionBase类,以便可以针对使用此类的程序集编译主代码。而不是在运行时加载包含特定基类的程序集

通常的警告:你需要有很好的理由和理解走这条路。即现有的外部代码是考虑这种方法的原因。
“不要在家里这样做,由经过培训的专业人员在封闭的课程上执行”。

您可以通过在使用派生类之前加载实现基类的不同程序集来进行一次性基类交换。但是这种方法不会使您的代码正常工作,因为您将无法编译这些代码,但是将对不同基类的方法的访问转移到单独的函数可能会正常工作

您可以添加包含所有基类中所有可能的方法/属性的UnionBase类,以便可以针对使用此类的程序集编译主代码。而不是在运行时加载包含特定基类的程序集

通常的警告:你需要有很好的理由和理解走这条路。即现有的外部代码是考虑这种方法的原因。
“不要在家里这样做,由经过培训的专业人员在封闭的课程上执行”。

可以使用基于编译时的解决方案来实现另一种可能的解决方案,即能够无缝地向现有类型注入新方法和接口,以及修改(截取)现有的。

可以使用基于编译时的解决方案实现另一种可能的解决方案,即能够无缝地向现有类型注入新方法和接口,以及修改(截取)现有类型。

实际上有一个很好的理由让您可以交换基类。假设您想修改基类,但不想干扰当前的代码库,因为它是在其他团队之间共享的。假设有10+个派生类从基继承。您可以创建10多个自定义派生类来覆盖基类,但这需要大量的工作。这就是你要做的。问题的关键是创建接口和基代理类

class Program
{
    static void Main(string[] args)
    {
          IActionable action = new Derived<Base1>();
          action.open();
          action = new Derived<Base2>();
          action.open();

     }
}

 // Proxybase is a fake base class. ProxyBase will point to a real base1 or
 // base2
public class Derived<T>:ProxyBase,IActionable
{
    public Derived():base(typeof(T))    

    // the open function is not overriden in this case allowing
    // the base implementation to be used
}

// this looks like the real base class but it is a fake
// The proxy simply points to the implementation of base1 or base2 instead
public abstract class ProxyBase: IActionable
{
    IActionable obj;
    public ProxyBase(Type type,params object[] args)
    {
             obj = (IActionable)Activator.CreateInstance(type,args);   
    }

    public virtual void open()
    {
          obj.open();
    }
}

// notice base1 and base2 are NOT abstract in this case
// consider this the original implementation of the base class
public class Base1: IActionable
{
      public virtual void open()
      {
            Console.WriteLine("base1 open");
      }

}

// here base2 acquired the functionality of base1 and hides base1's open 
   function
// consider this implementation the new one to replace the original one
public class Base2: Base1, IActionable
{
     public new virtual void open()
     {
           Console.WriteLine("base2 open");
     }
}

public interface IActionable
{
    void open();
}
更新:
尽管这个答案是可行的,但现实情况是继承引入了耦合,这使得这个练习充其量也很困难。此外,在实际场景中,您的需求可能会导致您希望从多个基类派生,这在c#中是不可能的。如果您想交换基类,最好使用桥接设计模式(它实际上完全避免了继承,从而避免了耦合)。

实际上有一个很好的理由让您可以交换基类。假设您想修改基类,但不想干扰当前的代码库,因为它是在其他团队之间共享的。假设有10+个派生类从基继承。您可以创建10多个自定义派生类
base1 open
base2 open