繁体   English   中英

强制子类将自身作为通用参数传递给基类

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM