在运行时扩展类

时间:2012-06-21 14:40:08

标签: c# .net

可能我无法用语言完全解释我想要实现的目标,但我认为这个示例代码可以做到:

class A
{
    public string Name
    {
        get;
        set;
    }
    public virtual void Say()
    {
        Console.WriteLine("I am A");
        Console.Read();
    }

    public bool ExtendA;

    public A GetObject()
    {
        if (ExtendA)
            return new B();

        return this;
    }
}

internal class B : A
{
    public override void Say()
    {
        Console.WriteLine(string.Format("I am {0}",Name));
        Console.Read();
    }
}

class Program
{
    static void Main(string[] args)
    {          
       var a = new A() {ExtendA = true,Name="MyName"};
        A ab = a.GetObject();            
    } 
}

根据上面的代码,当字段Exitend A设置为true时,再次尝试从同一个对象实例获取相同类型的对象时,我得到了对象,但是它丢失了属性的名称”。

有任何建议我如何使用A?

的属性返回B类

由于

2 个答案:

答案 0 :(得分:5)

我建议您阅读有关设计模式的书籍或其他资源。为此,您将使用工厂模式。

除了课程A和课程AFactory之外,您还有基础课程B : A和课程BFactory

在运行时,您可以选择要实例化的内容:A或B使用工厂:

IFactory factory = iWantClassA? new AFactory():new BFactory();    A = factory.CreateInstance();

虽然我同意@ArnaudF,但我看不出你想要完成什么。为什么不直接创建子类B?

更新:

重新阅读你的问题后,听起来你真的需要一个类的复制构造函数,如下所示:

public class A {
    public A() {
        // Default constructor
    }
    public A(A other) {
        // Copy-constructor. Members of other will be copied into this instance.
    }
}

public class B : A {
    public B() {

    }
    public B(A other) : base(other) { // Notice how it calls the parent class's copy-constructor too
    }
}

然后在运行时将A的实例“升级”为B的实例,只需使用复制构造函数:

A a = new A();
// some logic here
B upgradedA = new B( a );

答案 1 :(得分:1)

我不确定您的最终目标是什么,但我想让您了解ExpandObject类型,以防您不了解它。

这使您可以在运行时动态地向对象添加属性和方法,如下面的代码所示:

using System;
using System.Dynamic;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic expando = new ExpandoObject();

            expando.Name = "Name";  // Add property at run-time.
            expando.PrintName = (Action) (() => Console.WriteLine(expando.Name)); // Add method at run-time.

            test(expando);
        }

        private static void test(dynamic expando)
        {
            expando.PrintName();
        }
    }
}