基于抽象类型创建类

时间:2013-05-07 14:43:48

标签: c# oop

我有几个基于标准抽象类的类,它们将从数据表中加载(对于我使用int数组的样本)。该类将按类型启动,然后加载该类的特定详细信息。 Currenlty我使用switch语句执行此操作但是可以通过其他方式执行此操作吗?

class Program
{
    static void Main(string[] args)
    {
        var list = new[] {1, 1, 3, 2, 2, 4};
        TypeBase typeClass = null;
        foreach (var i in list)
        {
            switch (i)
            {
                case 1:
                    {
                        typeClass = new Type1();
                        break;
                    }
                case 2:
                    {
                        typeClass = new Type2();
                        break;
                    }
                case 3:
                    {
                        typeClass = new Type3();
                        break;
                    }
            }
        }
        if (typeClass != null)
        {
            typeClass.LoadDetails();
        }
    }
}

public class TypeBase
{
    public int Type { get; set; }
    public virtual void LoadDetails()
    {
        throw new NotImplementedException();
    }
}

public class Type1 : TypeBase
{
    public override void LoadDetails()
    {
        // Load type Specific details
    }
}

public class Type2 : TypeBase
{
    public override void LoadDetails()
    {
        // Load type Specific details
    }
}

public class Type3 : TypeBase
{
    public override void LoadDetails()
    {
        // Load type Specific details
    }
}

2 个答案:

答案 0 :(得分:3)

有几种解决方案。

<强> 1。使用反射创建类型

Nair已经提供了这个解决方案。由于我希望您的类型不会被称为Type1Type2等,我认为这对您不起作用。

<强> 2。将类型存储在类型为

的词典中

创建一个将替换您的开关/案例的字典。它包含您需要创建的类型:

Dictionary<int, Type> types = new Dictionary<int, Type>
{
    {1, typeof(Type1)},
    {2, typeof(Type2)},
    {3, typeof(Type3)}
};

使用它来创建你的类型:

Type type;
if (types.TryGetValue(i, out type))
{
    TypeBase typeClass = (TypeBase)Activator.CreateInstance(type);
    typeClass.LoadDetails();
}

此解决方案比解决方案#1更快,因为只使用了一个“反射”操作。

第3。使用工厂方法在词典中存储类型

创建一个将替换您的开关/案例的字典。它将包含工厂方法:

Dictionary<int, Func<TypeBase>> factories = new Dictionary<int, Func<TypeBase>>
{
    {1, () => new Type1()},
    {2, () => new Type2()},
    {3, () => new Type3()}
};

使用它来创建你的类型:

Func<TypeBase> factory;
if (factories.TryGetValue(i, out factory))
{
    TypeBase typeClass = factory();
    typeClass.LoadDetails();
}

此解决方案比解决方案#2更快,因为没有使用反射。

<强> 4。将类型存储在带有实例的词典中

创建一个将替换您的开关/案例的字典。它将包含您的类型的实例。此解决方案仅在这些实例不可变且在调用期间不会更改状态时才起作用。

Dictionary<int, TypeBase> typeClasses = new Dictionary<int, TypeBase>
{
    {1, new Type1()},
    {2, new Type2()},
    {3, new Type3()}
};

使用它来创建你的类型:

TypeBase typeClass;
if (baseClasses.TryGetValue(i, out baseClass))
{
    typeClass.LoadDetails();  
}

此解决方案比解决方案#3更快,因为每次调用都不会创建实例。

一些附注

  • 为什么不使用一个成员LoadDetails的界面?在您的示例中,永远不会使用成员Type
  • 为什么不将TypeBase.LoadDetails作为抽象方法?
  • 如果您的keys始终属于Int32类型并且处于连续范围内,则可以考虑使用List<T>甚至数组,这将比字典更快。< / LI>

答案 1 :(得分:1)

理想情况下,您应该遵循工厂方法来满足此类要求。另外,如果您愿意为您的子类遵循约定,那么便宜的技巧将如下所示。

using System;
using System.Runtime.Remoting;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var list = new[] {1, 1, 3, 2, 2, 4};
            TypeBase typeClass = null;
            foreach (var i in list)
            {
                ObjectHandle handle = Activator.CreateInstanceFrom("ConsoleApplication1", string.Format("{0}{1}", "Type", i));//Program- Name of the assembl
                var typeBase = (TypeBase) handle.Unwrap();
                typeBase.Type = i;
                typeClass.LoadDetails();
            }
        }
    }

    public class TypeBase
    {
        public int Type { get; set; }

        public virtual void LoadDetails()
        {
            throw new NotImplementedException();
        }
    }

    public class Type1 : TypeBase
    {
        public override void LoadDetails()
        {
            // Load type Specific details
        }
    }
}

注意: 我个人不会遵循这样的方法,对工厂方法或公平数量的交换机会更满意。这只是为了闪现一种可能性。请相应地进行测试和修改(如果决定遵循)

相关问题