我想强制我的子类将自己作为泛型参数传递给父类。
例如:
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的任何其他子项。
(上面的代码是一种伪代码,仍然无法编译)。
答案 0 :(得分:2)
你可以这样做:
public class BaseClass<T> where T: BaseClass<T> { }
public class ChildClass : BaseClass<ChildClass> { }
但是,这并不强迫使用ChildClass
作为通用参数。你可以这样做public class OtherChildClass : BaseClass<ChildClass> { }
这会破坏&#34; coontract&#34;你想强制执行。
答案 1 :(得分:1)
直接的答案是,如果您访问静态方法,那么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();
}
}
希望这有帮助
答案 2 :(得分:1)
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
行为,我们也会检查每个实例的初始化。它的速度和我一样快,但它仍然是多余的。