簡體   English   中英

C#:對子類類型的通用方法約束

[英]C#: generic method constraint on subclassed types

我有兩種基類:

public class Parent { }
public abstract class Child : Parent 
{
    string ChildKey { get; set; }
}

來自父母,有很多孩子:

public class Kid1 : Parent { public string Name { get; set; } }
public class Kid2 : Parent { public long Number { get; set; } }
...

還有許多兒童是特殊的兒童群體,具有額外的屬性:

public class Child1 : Child { public string Street { get; set; } }
public class Child2 : Child { public long Account { get; set; }}

現在,我有兩個通用的存儲庫類,其中的“特殊的”通過使用附加的過濾器在附加屬性上表現得更加具體:

public class Repository<T> : IRepository<T> where T : Parent 
{ 
    public IEnumerable<T> GetAll() { return something; }
}
public class ChildRepository<T> : Repository<T>, IChildrenRepository<T> where T : Child 
{ 
    public override IEnumerable<T> GetAll() { return base.GetAll().Where(x => x.ChildKey == "y"); }
}

與接口:

public interface IRepository<T> where T : Parent
{ IEnumerable<T> GetAll(); }
public interface IChildRepository<T> : IRepository<T> where T : Child { }

我還需要GetAll()結果的類型安全。

現在,我需要一個通用方法來創建所需的存儲庫:

IRepository<T> GetRepository() where T : WhatConstraint
{
    if (typeof(Child).IsAssignableFrom(T))
        return new ChildRepository<T>();    // return 1
    return new Repository<T>();             // return 2
}

正確的約束是什么? return 1需要Child-Constraint(對於Return 2是錯誤的),它表示類型T不能用作方法中的類型參數,因為沒有從T到Child的隱式引用轉換。

T:Child-constraint在ChildRepository中更為精確(因此很有用,因為我可以依賴某些屬性)。 如果我使用相同的T:存儲庫的父約束,則必須一直檢查T是否始終從Child派生...

有什么解決辦法嗎?

好的,這是一個詳細的解決方案(可以寫得更短也更不易讀)。 由於存儲庫和ChildRepository具有沖突的約束(這對存儲庫有利,但對GetRepository-factory不利),因此無法使用new-keyword創建ChildRepository。 我必須通過CreateInstance創建此對象。

IRepository<T> GetRepository() where T : Parent
{
    if (typeof(Child).IsAssignableFrom(T))
    {
        Type childType = typeof(T);  // which is both, Parent and Child
        Type classType = typeof(ChildRepository<>);
        Type[] typeParams = { childType };
        Type repositoryType = classType.MakeGenericType(typeParams);
        return Activator.CreateInstance(resultType) as IRepository<T>;
    }
    return new Repository<T>();
}

該解決方案的缺點:更復雜的代碼分析,不清楚的結果可為空性,不是真正直觀的可讀性(尤其是現有的約束)。 但這有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM