![](/img/trans.png)
[英]Is letting a class pass itself as a parameter to a generic base class evil?
[英]Force a child class to pass itself as the Generic parameter to the base class
我想强制我的子类将自身作为通用参数传递给父类。
例如 :
class BaseClass<T> where T: BaseClass
{
//FullClassName : Tuple [Save,Update,Delete]
Dictionary<string,Tuple<delegate,delegate,delegate>> dict = new Dictionary...;
static BaseClass()
{
RegisterType();
}
private static void RegisterType()
{
Type t = typeof(T);
var props = t.GetProperties().Where(/* Read all properties with the SomeCustomAttribute */);
/* Create the delegates using expression trees and add the final tuple to the dictionary */
}
public virtual void Save()
{
delegate d = dict[t.GetType().FullName];
d.Item1(this);
}
}
class ChildClass : BaseClass<ChildClass>
{
[SomeCustomAttribute]
public int SomeID {get;set;}
[SomeCustomAttribute]
public string SomeName {get; set;}
}
public class Program
{
public static void Main(string[] args)
{
ChildClass c = new ChildClass();
c.Save();
}
}
显然,以上代码无法编译。 我要重申一下:我希望子类将自身作为通用参数而不是BaseClass的任何其他子类传递。
(以上代码是一种伪代码,将仍然无法编译)。
你可以这样做:
public class BaseClass<T> where T: BaseClass<T> { }
public class ChildClass : BaseClass<ChildClass> { }
但这并不会迫使您使用ChildClass
作为通用参数。 您可以执行此public class OtherChildClass : BaseClass<ChildClass> { }
,这将破坏您要强制执行的“契约”。
直接的答案是,如果您访问静态方法,则typeof(T)将为您提供反射类型。
但是,可能有比使用反射更好的解决方案。 选项:
1)子类上的静态构造函数。
2)在基类中声明的抽象方法。
我不知道应用程序,但是如果我想使用静态构造函数,我会担心自己的设计,如果基类需要初始化子类,我也会担心。
我建议将注入作为解决方案而不是继承。 它提供了出色的单元测试和通常更好的体系结构。
更多信息(在初始发布之后),这是我的首选解决方案:
public interface IRegesterable
{
void Register();
}
public class Widget : IRegesterable
{
public void Register()
{
// do stuff
}
}
public class Class1
{
public Class1(IRegesterable widget)
{
widget.Register();
}
}
希望这可以帮助
ConcurrentDictionary
用作Set<Type>
。 我们可以在Set<Type>
检查类型是否已初始化。 如果不是,我们在该类型上运行RegisterType
。
public abstract class BaseClass
{
//Concurrent Set does not exist.
private static ConcurrentDictionary<Type, bool> _registeredTypes
= new ConcurrentDictionary<Type, bool>();
protected BaseClass()
{
_registeredTypes.GetOrAdd(GetType(), RegisterType);
}
private static bool RegisterType(Type type)
{
//some code that will perform one time processing using reflections
//dummy return value
return true;
}
}
public class ChildClass : BaseClass
{
}
但是,这种模式存在一些效率低下的问题。
object.GetType()
非常慢,而且效率低下。 HashSet
行为,我们也在检查每个实例的初始化。 它的速度尽我所能,但仍然是多余的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.