基于抽象类型创建类
我有基于标准抽象类的相关类,它们将从数据表(对于我使用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
}
}
有几种解决方案。
1.创建类型的反射
该解决方案已被奈尔给出。因为我预计你的类型不会被称为Type1
,Type2
等,我认为这不适合你。
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>
或甚至是一个数组,该数组将比字典更快。
将看看并创建一个实现使用你的消化看起来非常intresting .. ;-) – 2013-05-14 17:56:02
理想情况下,您应该按照工厂方法来满足这样的要求。否则,如果你很乐意遵循约定为你的子类,那么一个便宜的技巧将如下所示。
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
}
}
}
注:我个人不会遵循这样的做法,并会更高兴的工厂方法或相当数量的开关。这只是闪现一个可能性而已。请相应测试并修改(如果决定遵循)
可以请你解释关于你的陈述更多一点:理想情况下,你应该按照工厂方法来满足这样的要求 – 2013-05-07 16:51:07
工厂方法是一种理想的设计模式。你可以阅读更多关于它[这里](http://www.dofactory.com/Patterns/PatternFactory.aspx#_self2)。不要限制自己尝试搜索更多的工厂方法实现。它的好处是,它为您提供了更多静态类型的语言功能,并且没有运行时异常的空间。这就是为什么我比我的上述选秀更喜欢工厂。 – Nair 2013-05-07 17:45:26
您可以使用反射来尝试解决该类型名称:'变种类型= Type.GetType(“类型名称”)'和使用'Activator.CreateInstance(类型)'创建一个实例 – Charleh 2013-05-07 14:46:07