典型情况如下。
class ServiceBase
{
public virtual InstanceBase GetObject() { return null; }
}
class ServiceA : ServiceBase
{
public override InstanceBase GetObject()
{
var v = new InstanceA();
v.Method();
return v;
}
}
class ServiceB : ServiceBase
{
public override InstanceBase GetObject()
{
var v = new InstanceB();
v.Method();
return v;
}
}
class InstanceBase
{
public virtual void Method() { }
}
class InstanceA : InstanceBase
{
public override void Method(){}
}
class InstanceB : InstanceBase
{
public override void Method() { }
}
不同的服务处理不同的实例类。但是GetObject的代码对于所有服务都是类似的。我想通过扩展基类'执行最多的GetObject方法来减少代码库。
class ServiceBase
{
public virtual InstanceBase GetObject<T>()
{
var v= (InstanceBase)Activator.CreateInstance(typeof(T), new object[] { });
v.Method();
return v;
}
}
这似乎是一种实现方式。但是我不太担心使用反射,因为它可能会遇到性能问题。有没有更好的方法来实现这一目标?
答案 0 :(得分:5)
是的,有两种方式:
1)通用方法:
class ServiceBase<T> where T : InstanceBase, new()
{
public InstanceBase GetObject() //you can make the return type even 'T'
{
var v = new T();
v.Method();
return v;
}
}
class ServiceA : ServiceBase<InstanceA>
{
}
class ServiceB : ServiceBase<InstanceB>
{
}
这更好,因为它具有最少的代码重复,但我不确定通用性是否会成为一个麻烦。
2)如果不适合,您可以要求基类提供自己的InstanceBase
。这看起来更简洁。像:
abstract class ServiceBase
{
public abstract InstanceBase Instance { get; }
public InstanceBase GetObject() //you can make the return type even 'T'
{
Instance.Method();
return Instance;
}
}
class ServiceA : ServiceBase
{
public override InstanceBase Instance { get; } //return new InstanceA() here
}
class ServiceB : ServiceBase
{
public override InstanceBase Instance { get; } //return new InstanceB() here
}
现在,从重写的属性Instance
返回InstanceBase
的新实例或已经实例化的实例。这取决于你的逻辑,但是从所显示的方法来看,你每次都必须返回一个新的实例。
哪种适合你取决于你的背景。不管是什么,请考虑一下:
1)这种做法很糟糕。
public virtual InstanceBase GetObject<T>()
{
var v= (InstanceBase)Activator.CreateInstance(typeof(T), new object[] { });
v.Method();
return v;
}
首先,你必须在调用函数时指定类型参数,二,每个人都有可能把事情搞得一团糟。
ServiceA a = new ServiceA();
a.GetObject<InstanceB>(); // not probably what you want.
2)在任何情况下,如果你想要它,你可以为泛型类型参数new()
提供T
约束。
3)如果要使用默认构造函数进行实例化,则无需指定空参数集合。这样做:
var v= (InstanceBase)Activator.CreateInstance(typeof(T));
// or just new T();
4)您似乎没有在GetObject
方法中使用任何实例成员。如果是这种情况,那么您可以使用静态方法。这应该是静态的还是非静态的,取决于您想要进行的调用。请记住static
。
public static InstanceBase GetObject() //you can make the return type even 'T'
{
var v = new T();
v.Method();
return v;
}
//can call like this too:
ServiceA.GetObject(); //etc
答案 1 :(得分:2)
只需指定T是可以实例化的类:
public virtual InstanceBase GetObject<T>() where T : class, new()
然后,您可以在不使用反射的情况下实例化对象:
T myInstance = new T();
答案 2 :(得分:0)
性能肯定会受到打击。请考虑以下代码:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Create 1MM ServiceA...");
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
var o = new ServiceA();
var obj = o.GetObject();
}
sw.Stop();
Console.WriteLine("{0} ms", sw.ElapsedMilliseconds);
Console.WriteLine();
Console.WriteLine("Create 1MM ServiceB...");
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
var o = new ServiceB();
var obj = o.GetObject();
}
sw.Stop();
Console.WriteLine("{0} ms", sw.ElapsedMilliseconds);
Console.WriteLine();
Console.WriteLine("Create 1MM GenericServiceA...");
sw= new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
var o = new GenericServiceBase();
var obj = o.GetObject<ServiceA>();
}
sw.Stop();
Console.WriteLine("{0} ms", sw.ElapsedMilliseconds);
Console.WriteLine();
Console.WriteLine("Create 1MM GenericServiceB...");
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
var o = new GenericServiceBase();
var obj = o.GetObject<ServiceB>();
}
sw.Stop();
Console.WriteLine("{0} ms", sw.ElapsedMilliseconds);
Console.WriteLine();
}
}
class GenericServiceBase
{
public virtual InstanceBase GetObject<T>()
where T : ServiceBase
{
var v = (ServiceBase)Activator.CreateInstance(typeof(T), new object[] { });
return v.GetObject();
}
}
class ServiceBase
{
public virtual InstanceBase GetObject() { return null; }
}
class ServiceA : ServiceBase
{
public override InstanceBase GetObject()
{
var v = new InstanceA();
v.Method();
return v;
}
}
class ServiceB : ServiceBase
{
public override InstanceBase GetObject()
{
var v = new InstanceB();
v.Method();
return v;
}
}
class InstanceBase
{
public virtual void Method() { }
}
class InstanceA : InstanceBase
{
public override void Method() { }
}
class InstanceB : InstanceBase
{
public override void Method() { }
}
及其输出:
Create 1MM ServiceA...
34 ms
Create 1MM ServiceB...
33 ms
Create 1MM GenericServiceA...
1226 ms
Create 1MM GenericServiceB...
1255 ms
更新:如果您在约束中使用new
关键字加入小技巧,则会得到以下结果:
Create 1MM ServiceA...
35 ms
Create 1MM ServiceB...
32 ms
Create 1MM GenericServiceA...
182 ms
Create 1MM GenericServiceB...
177 ms
超过1MM的性能并不差,但它仍然存在。