我有很多模型类,其中填充了从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; }
}
所有模型类还具有在db中创建/更新相关实体的方法。例如,“汽车”类的方法是:
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字段绑定?
答案 0 :(得分:0)
这种方式:
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; }
}
然后,您必须覆盖要处理的每个不同类的方法。
答案 1 :(得分:0)
建立一个abstract
超类的想法是绝对好的。但是,它不必是通用的。它应该只包含所有常见行为。说了这一点,您的Entitity
类还应该具有abstract ID
属性:
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 abstract int Id { get; set; }
}
现在,在实现类中,您可以实现abstract
属性,以返回具体的CarId
,例如:
public class Car : Entity
{
public int CarId { get; set; }
public int Id => CarId;
}
或者,您可以完全忽略CarId
类中的Car
属性,而仅抽象类中的Id
:
public class Car : Entity
{
public int Id get; set; }
}
无论您现在选择这两种方法中的哪一种,都有具有Id
成员的Add
方法,如下所示:
public async Task<bool> Add()
{
using (var client = new HttpClient())
{
string url = Secrets.ApiAddress + $"Create{this.GetType().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();
// you don´t need to knoe the actual type, all you need is its Id, so an Entity is just fine
Entity e = JsonConvert.DeserializeObject(rString);
this.Id = e.Id;
return true;
}
else
{
return false;
}
}
}
答案 2 :(得分:0)
您可能想看看存储库模式。在存储库模式中,使用对实体抽象类中的属性进行基本CRUD操作的基础存储库。然后,创建派生的存储库类,以对实体特定的属性进行操作。 如果您仍然想在模型类中进行操作,则可以执行以下操作。
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 virtual void Add(){
//operation using base properties
}
public class Car : Entity<Car>
{
public int CarId { get; set; }
public override void Add(){
//do custom operation or call base.Add() or whatever you want
}
}
}
答案 3 :(得分:0)
我通过实施小的解决方法解决了该问题。当我将HimBromBeere的建议落实到位时,“编辑”已经起作用。为了使“添加”正常工作,我不得不将Entity类更改为:
public abstract class Entity<T>
{
[Browsable(false)]
public string AddedItem { get; set; }
public virtual 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();
AddedItem = rString;
return true;
}
else
{
MessageBox.Show("Serwer zwrócił błąd przy próbie utworzenia rekordu. Wiadomość: " + result.ReasonPhrase);
return false;
}
}
}
}
并将派生类更改为:
public class Car : Entity<Car>
{
public async override Task<bool> Add()
{
bool x = await base.Add();
if (x)
{
try
{
Car _this = JsonConvert.DeserializeObject<Car>(AddedItem);
this.CarId = _this.CarId;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
MessageBox.Show("Tworzenie nowego rekordu zakończone powodzeniem!");
return true;
}
else
{
return false;
}
}
}
我发现HimBromBeere的答案最有帮助,因此选择他的帖子回答了我的问题。