如何应用泛型约束来接受多级继承 C#

How to apply generic constraint to accept multi level of inheritance C#

我正在寻找一种方法来支持通用类型约束的多级继承。

通用通用接口

public interface ICommon<T>
{
    T OrignalData {get;set;}
    string ChangeJson {get;set;}
    T Merged {get;set;}
    void Inject();
}

公共基础 class 实现 ICommon

public class Base <T>: ICommon<T>
{
    public T OrignalData {get;private set;}
    public string ChangeJson {get;set;}
    public T Merged {get;private set;}
    public void Inject(T orignal)
    {
        if (orignal == null)
            return;
       
        var settings = new JsonSerializerSettings
        {
            ObjectCreationHandling = ObjectCreationHandling.Auto
        };
        dynamic merged = orignal.Clone();
        JsonConvert.PopulateObject(this.ChangeJson, merged, settings);
        this.Merged  = merged;
        this.Orignal = orignal;
    }
}

部门class继承基础class

public class Deparment : Base<Deparment>
{
}

OrgnizationDepartment class 继承 Deparment

public class OrgnizationDepartment : Deparment
{

}

class 查看期望 ICommon 必须在传递的调用上实现

public class View<T> where T : ICommon<T>
{
   //This class is totally dynamic to visualize any json data along with  old and new value of requested json for any class like department or org..
}

测试

public class Test
{
    public void TestConstraint()
    {
        //No error 
        var deptView = new View<Deparment>();

        //Error as Base not directly implemented on OrgnizationDepartment 
        var orgView = new View<OrgnizationDepartment>();
    }
}

如何定义也应支持多级别的约束。

一个 的出路是“组合优于继承”。

这是一个简单的例子,仍然比较接近你的代码:

using System;
using Newtonsoft.Json;
                    
public class Program
{
    public static void Main()
    {
        //No error 
        var deptView = new View<Deparment>();

        //Formerly Error 
        var orgView = new View<OrgnizationDepartment>();
    }
}

public interface ICommon<T> where T : ICloneable
{
    // returns a tuple
    (T,T,string) Inject(T original, string change);
}

public class Base <T>: ICommon<T> where T : ICloneable
{
   // we can reuse this...
   private readonly JsonSerializerSettings  settings = new JsonSerializerSettings
        {
            ObjectCreationHandling = ObjectCreationHandling.Auto
        };

    public (T,T,string) Inject(T original, string change)
    {
        if (original is null)
            return default;
        
        // this forces T to implement ICloneable ... just saying...
        dynamic merged = original.Clone();
        
        JsonConvert.PopulateObject(change, merged, settings);
        return (original, merged, change);
    }
}

public class Deparment : ICloneable, ICommon<Deparment>
{
    // could also be created in ctor. Maybe use Ctor injection.
    private readonly Base<Deparment> common = new Base<Deparment>();
    public object Clone(){return this;} // this is of course nonsense. Clone properly! I did this to avoid dotnetfiddle screaming at me.
    public (Deparment, Deparment, string) Inject(Deparment original, string change){
        return common.Inject(original, change);
    }
}

public class OrgnizationDepartment : ICloneable, ICommon<OrgnizationDepartment>
{
    private readonly Base<OrgnizationDepartment> common = new Base<OrgnizationDepartment>();
    public object Clone() {return this;}
    public (OrgnizationDepartment, OrgnizationDepartment, string) Inject(OrgnizationDepartment original, string change){
        return common.Inject(original, change);
    }
}