首页 > 解决方案 > 在父方法中使用子属性

问题描述

我有许多模型类,我用从 Web api 服务获取的数据填充它们。所有类共享许多属性,如创建日期等:

public class Car
    {
        public int CarId { get; set; }
        [Browsable(false)]
        public int CreatedBy { get; set; }
        [DisplayName("Utworzył")]
        public string CreatedByName { get; set; }
        [DisplayName("Data utworzenia")]
        public DateTime CreatedOn { get; set; }
        [Browsable(false)]
        public int? LmBy { get; set; }
        [DisplayName("Zmodyfikował")]
        public string LmByName { get; set; }
        [DisplayName("Data modyfikacji")]
        public DateTime? LmOn { get; set; }
        [Browsable(false)]
        public int TenantId { get; set; }
        [Browsable(false)]
        public string TenantName { get; set; }
    }

所有模型类还具有在数据库中创建/更新相关实体的方法。例如“汽车”类的方法是:

public async Task<bool> Add()
        {
            using (var client = new HttpClient())
            {
                string url = Secrets.ApiAddress + $"CreateCar?token=" + Secrets.TenantToken + "&UserId=" + RuntimeSettings.UserId;
                var serializedProduct = JsonConvert.SerializeObject(this);
                var content = new StringContent(serializedProduct, Encoding.UTF8, "application/json");
                var result = await client.PostAsync(new Uri(url), content);
                if (result.IsSuccessStatusCode)
                {
                    var rString = await result.Content.ReadAsStringAsync();
                    T _this = JsonConvert.DeserializeObject<T>(rString);
                    this.CarId = _this.CarId;
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        public async void Edit()
        {
            using (var client = new HttpClient())
            {
                string url = Secrets.ApiAddress + $"EditCar?token=" + Secrets.TenantToken + "&id={0}&UserId={1}";
                var serializedProduct = JsonConvert.SerializeObject(this);
                var content = new StringContent(serializedProduct, Encoding.UTF8, "application/json");
                var result = await client.PutAsync(String.Format(url, this.CarId, RuntimeSettings.UserId), content);
            }
        }

所以我认为最好为所有其他模型类创建一个模型类。它具有所有共享属性:

public abstract class Entity<T>
    {
        [Browsable(false)]
        public int CreatedBy { get; set; }
        [DisplayName("Utworzył")]
        public string CreatedByName { get; set; }
        [DisplayName("Data utworzenia")]
        public DateTime CreatedOn { get; set; }
        [Browsable(false)]
        public int? LmBy { get; set; }
        [DisplayName("Zmodyfikował")]
        public string LmByName { get; set; }
        [DisplayName("Data modyfikacji")]
        public DateTime? LmOn { get; set; }
        [Browsable(false)]
        public int TenantId { get; set; }
        [Browsable(false)]
        public string TenantName { get; set; }
    }

它将像下面这样使用:

public class Car : Entity<Car>
    {
        public int CarId { get; set; }
    }

我遇到的问题是方法。如果我将它们保留在父类中(因为 90% 的逻辑是共享的,所以不要为每个子类创建它们),我不能在父类的方法中使用子类的 id 属性(CarId),因为父类中不存在这样的属性:

public async Task<bool> Add()
        {
            using (var client = new HttpClient())
            {
                string url = Secrets.ApiAddress + $"Create{typeof(T).Name}?token=" + Secrets.TenantToken + "&UserId=" + RuntimeSettings.UserId;
                var serializedProduct = JsonConvert.SerializeObject(this);
                var content = new StringContent(serializedProduct, Encoding.UTF8, "application/json");
                var result = await client.PostAsync(new Uri(url), content);
                if (result.IsSuccessStatusCode)
                {
                    var rString = await result.Content.ReadAsStringAsync();
                    T _this = JsonConvert.DeserializeObject<T>(rString);
                    this.CarId = _this.CarId; // CarId doesn't exist in parent, it's child's property
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        public async void Edit()
        {
            using (var client = new HttpClient())
            {
                string url = Secrets.ApiAddress + $"Edit{typeof(T).Name}?token=" + Secrets.TenantToken + "&id={0}&UserId={1}";
                var serializedProduct = JsonConvert.SerializeObject(this);
                var content = new StringContent(serializedProduct, Encoding.UTF8, "application/json");
                var result = await client.PutAsync(String.Format(url, this.CarId, RuntimeSettings.UserId), content); // CarId doesn't exist in parent, it's child's property
            }
        }

可能如果我使用更通用的 ID 属性名称(Id 而不是 CarId),它会更简单,但假设我必须坚持使用自定义名称(“CarId”,“EmployeeId”) - 我的选择是什么?

也许我可以在父级中创建通用 ID 属性,并在继承时以某种方式将其与子级的相应 id 字段绑定?

标签: c#oopinheritance

解决方案


这边走:

public abstract class Entity
{
    [Browsable(false)]
    public int CreatedBy { get; set; }
    [DisplayName("Utworzył")]
    public string CreatedByName { get; set; }
    [DisplayName("Data utworzenia")]
    public DateTime CreatedOn { get; set; }
    [Browsable(false)]
    public int? LmBy { get; set; }
    [DisplayName("Zmodyfikował")]
    public string LmByName { get; set; }
    [DisplayName("Data modyfikacji")]
    public DateTime? LmOn { get; set; }
    [Browsable(false)]
    public int TenantId { get; set; }
    [Browsable(false)]
    public string TenantName { get; set; }
}


public class Car : Entity
{
    public int CarId { get; set; }
}

然后,您必须重写要处理的每个不同类的方法。


推荐阅读