C# 泛型类及其子类

C# 泛型类及其子类,c#,generic-programming,C#,Generic Programming,我有一个基类实体和一个增强类,比如Home public class Home : Entity { public int CityId{get;set;} } public class Town : Entity { public int CityId {get;set} public Home CityHall {get;set;} public List<Home > Homes{get;set;} } 公共类主页:实体 { public

我有一个基类实体和一个增强类,比如Home

public class Home : Entity
{
    public int CityId{get;set;}
}

public class Town : Entity 
{
    public int  CityId {get;set}
    public Home CityHall {get;set;}
    public List<Home > Homes{get;set;}
}
公共类主页:实体
{
public int CityId{get;set;}
}
公共类城镇:实体
{
public int CityId{get;set}
公共住宅城市墙{get;set;}
公共列表Homes{get;set;}
}
我想为小镇和它的孩子们设置城市ID 所以,第一次尝试,我做了以下几点

public class DataAccessBase<T> where T : Entity
{
    public int Add(T entity)
    {
        Type t = typeof(T);
        PropertyInfo prop = t.GetProperty("CityId");
        if (prop != null)
        {
            prop.SetValue(entity, 2);
        }
    }
}
公共类DataAccessBase,其中T:Entity
{
公共整数添加(T实体)
{
类型t=类型(t);
PropertyInfo prop=t.GetProperty(“CityId”);
如果(prop!=null)
{
属性设置值(实体,2);
}
}
}

这只适用于父级如何访问子级,我想对其进行一般性的讨论,因为我有一个DataaaAccessLayer,可以插入数据库一般性的内容。看起来有两个不相关的问题

  • 如果存在属性,如何在没有知识的情况下设置对象的属性:现有的反射解决了这个问题。请注意,这不是很C#的方式-您应该使用一些接口并将泛型限制到该接口,以允许对属性的强类型访问

  • 如何在不知道类型的情况下枚举“child”对象:传统的解决方案是为“GetChildren”功能添加接口。或者,您可以使用反射查找所有“子”类型的属性,并与所有类型为
    IEnumerable
    的属性组合

    如果您可以使用某种约定
    动态
    可以更容易地替代反射(即每种类型都公开
    子项
    属性来枚举它们:

    dynamic town = GetTown();
    foreach(dynamic child in town.Children) {...}
    

您可以直接设置属性,无需反射

entity.CityId = 1;
if(entity is Town) {
    var town = entity as Town;
    if(town.Homes!=null) {
        town.Homes.ForEach(t=> t.CityId = entity.CityId);
    }
}

您可以直接设置属性,无需反射否我有一个添加到数据库的通用类,因此我需要以通用方式执行@nkoside注意:我强烈建议不要使用“通用”一词对于常规类,为了避免与泛型混淆…您需要显示
实体
。您的问题不清楚。您需要更好地解释它。您的问题仍然非常令人困惑。您说您不知道传入类型,但您假设它有一个
CityId
属性,可以从分配到int。根本不清楚为什么此方法实际上是“通用的”;例如,使用单独的
Add(Home)
Add(Town)
方法(或其他一些非通用的实现)似乎要容易得多。您试图如何调用此方法?此泛型类是一个概念,我不知道提交类型或其子类fwiw,我更喜欢接口解决方案,而不是
dynamic
。例如
interface ihaschilden其中t:Entity{IEnumerable GetChildren();}
然后
Town:Entity,ihaschilden{…}
。但是,我认为这个问题还不够清楚,无法完全回答。@p.s.w.g确实-我只会使用
动态
作为反射的替代方案(即,如果无法更改代码以添加公共接口)我不确定您是否意识到这一点,但为了让其他读者清楚,
dynamic
实际上只是简单的旧反射的语法糖。C#编译器会将其转换为大致类似于
(IEnumerable)(town.GetType().GetProperty(“Children”).GetValue(town))