C# 如何重新构建模型类型以减少代码复制
我有3种型号:C# 如何重新构建模型类型以减少代码复制,c#,inheritance,C#,Inheritance,我有3种型号: public class BankA_Transaction : BanKTransactionMetaData { public string GROUPName { get; set; } public string ACC_ID { get; set; } public string ACCOUNT_NO { get; set; } } public class BankB_Transaction : BanKTransactionMetaDat
public class BankA_Transaction : BanKTransactionMetaData
{
public string GROUPName { get; set; }
public string ACC_ID { get; set; }
public string ACCOUNT_NO { get; set; }
}
public class BankB_Transaction : BanKTransactionMetaData
{
public string Name { get; set; }
public string ACC_ID { get; set; }
public string ACCOUNT_NO { get; set; }
}
public class BankC_Transaction : BanKTransactionMetaData
{
public string FullName { get; set; }
public string ACC_ID { get; set; }
public string ACCOUNT_NO { get; set; }
}
注意:实际的属性列表要长得多
所有这些都继承了保存到数据库时所需的一些字段
public class BanKTransactionMetaData
{
public String BankName { get; set; }
}
public void SaveBankA(BankA bankA)
{
bankA.BankName = "Bank_A";
string jsonText = JsonConvert.SerializeObject(bankA_Transaction, Formatting.Indented);
Code for saving...
这些模型由银行发送的文件中的记录填充,然后保存到数据库中。
作为此保存的一部分,我将记录转换为数据库所需的JSON
public class BanKTransactionMetaData
{
public String BankName { get; set; }
}
public void SaveBankA(BankA bankA)
{
bankA.BankName = "Bank_A";
string jsonText = JsonConvert.SerializeObject(bankA_Transaction, Formatting.Indented);
Code for saving...
目前我对储蓄银行a、储蓄银行a和储蓄银行B有不同的方法
在我看来,这是代码复制,我应该让所有模型更好地继承,以便使用基类型?而不是每个命名类型
我读过抽象类和虚拟类,因为我怀疑这正是我需要的,但我不知道如何将它们连接在一起
我不能只在SaveBankA中使用Object,因为我需要添加.BankName
是否有更好的架构来减少代码复制?也许您需要这样的架构 在基本服务类中:
protected void SaveBankTransaction(BankTransactionMetaData tran)
{
string jsonText = JsonConvert.SerializeObject(tran, Formatting.Indented);
// additional saving code
}
在儿童服务班:
public void SaveBankA(BankA bankA)
{
bankA.BankName = "Bank_A";
base.SaveBankTransaction(bankA);
}
也许你需要这样的东西 在基本服务类中:
protected void SaveBankTransaction(BankTransactionMetaData tran)
{
string jsonText = JsonConvert.SerializeObject(tran, Formatting.Indented);
// additional saving code
}
在儿童服务班:
public void SaveBankA(BankA bankA)
{
bankA.BankName = "Bank_A";
base.SaveBankTransaction(bankA);
}
创建两个接口,一个用于元数据(
IBankData
),另一个用于银行交易详细信息(IBankTransaction
)。IBankData
界面将维护对IBankTransaction
界面的引用。这还应允许您在需要时添加其他银行,例如银行D
public interface IBankData
{
string BankName { get; }
// ... additional bank meta data properties
// ...
IBankTransaction Transaction { get; set; }
}
public interface IBankTransaction
{
[JsonProperty("ACC_ID")]
string AccountId { get; set; }
[JsonProperty("ACCOUNT_NO")]
string AccountNumber { get; set; }
// ... additional shared bank transaction properties
// ...
}
仅供参考,我选择使用JsonProperty
属性来控制JSON键的名称,这允许根据最佳实践命名类属性,而不影响JSON属性名称
接下来,为您将要使用的每个银行实现接口。在每个银行中添加仅适用于每个实现的附加属性,即由于GroupName
属性仅由BankA
使用,因此此属性将添加到BankA
类中,而不是接口中。这同样适用于任何其他特定于银行的房地产
银行A
public class BankA : IBankData
{
public string BankName => "BankA";
public IBankTransaction Transaction { get; set; }
}
public class BankATransaction : IBankTransaction
{
// Bank A specific properties
[JsonProperty("GROUPName")]
public string GroupName { get; set; }
// ... additional Bank A specific properties
// ...
// interface implemented properties
public string AccountId { get; set; }
public string AccountNumber { get; set; }
}
银行B
public class BankB : IBankData
{
public string BankName => "BankB";
public IBankTransaction Transaction { get; set; }
}
public class BankBTransaction : IBankTransaction
{
// Bank B specific properties
public string Name { get; set; }
// ... additional Bank B specific properties
// ...
// interface implemented properties
public string AccountId { get; set; }
public string AccountNumber { get; set; }
}
银行C
public class BankC : IBankData
{
public string BankName => "BankC";
public IBankTransaction Transaction { get; set; }
}
public class BankCTransaction : IBankTransaction
{
// Bank B specific properties
public string FullName { get; set; }
// ... additional Bank B specific properties
// ...
// interface implemented properties
public string AccountId { get; set; }
public string AccountNumber { get; set; }
}
JsonConverter
由于IBankTransaction
是IBankData
中的一个属性,因此这将更改JSON结构。您可能不希望这样做,为了保留您的结构,可以在IBankData
接口上实现JsonConverter
。这将删除JSON中的事务对象,并将子属性移动到JSON根目录下
public class BankJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
if (t.Type != JTokenType.Object)
{
t.WriteTo(writer);
}
else
{
JObject o = (JObject)t;
JProperty transactionProperty = o.Properties().FirstOrDefault(p => p.Name == "Transaction");
o.Remove("Transaction");
JToken token = transactionProperty;
foreach (JToken ct in token.Children())
{
foreach (var prop in JProperty.FromObject(ct))
{
o.Add(prop);
}
}
serializer.Serialize(writer, o);
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
}
public override bool CanRead => false;
public override bool CanConvert(Type objectType)
{
return objectType.GetInterfaces().Contains(typeof(IBankData));
}
}
用法
对于使用示例,我创建了一些测试函数来准备数据,并添加了SaveBank
方法,您可以在实际代码中重新定位,因为这对您的解决方案很有意义
class Program
{
static void Main(string[] args)
{
string bankATransJson = GetBankATestJsonInput();
BankATransaction bankATransaction = JsonConvert.DeserializeObject<BankATransaction>(bankATransJson);
BankA bankA = new BankA();
bankA.Transaction = bankATransaction;
Console.WriteLine(SaveBank(bankA));
// output:
// {
// "BankName": "BankA",
// "GROUPName": "g54321",
// "ACC_ID": "A01",
// "ACCOUNT_NO": "A1111"
// }
string bankBInputJson = GetBankBTestJsonInput();
BankBTransaction bankBTransInput = JsonConvert.DeserializeObject<BankBTransaction>(bankBInputJson);
BankB bankB = new BankB();
bankB.Transaction = bankBTransInput;
Console.WriteLine(SaveBank(bankB));
// output:
// {
// "BankName": "BankB",
// "ACC_ID": "B02",
// "ACCOUNT_NO": "B2222",
// "Name": "Bank_Of_B
// }
string bankCInputJson = GetBankCTestJsonInput();
BankCTransaction bankCTransInput = JsonConvert.DeserializeObject<BankCTransaction>(bankCInputJson);
BankC bankC = new BankC();
bankC.Transaction = bankCTransInput;
Console.WriteLine(SaveBank(bankC));
// output:
// {
// "BankName": "BankC",
// "ACC_ID": "C03",
// "ACCOUNT_NO": "C3333",
// "FullName": "C Bank"
// }
}
public static string SaveBank(IBankData bankData)
{
// when calling the serialize object method, we pass our BankJsonConverter
string jsonText = JsonConvert.SerializeObject(bankData, Formatting.Indented, new BankJsonConverter());
// this example just returns the JSON text
// but you would implement your save logic as needed
return jsonText;
}
private static string GetBankATestJsonInput()
{
var obj = new { ACC_ID = "A01", ACCOUNT_NO = "A1111", GROUPName = "g54321" };
return JsonConvert.SerializeObject(obj);
}
private static string GetBankBTestJsonInput()
{
var obj = new { ACC_ID = "B02", ACCOUNT_NO = "B2222", Name = "Bank_Of_B" };
return JsonConvert.SerializeObject(obj);
}
private static string GetBankCTestJsonInput()
{
var obj = new { ACC_ID = "C03", ACCOUNT_NO = "C3333", FullName = "C Bank" };
return JsonConvert.SerializeObject(obj);
}
}
类程序
{
静态void Main(字符串[]参数)
{
字符串bankATransJson=GetBankATestJsonInput();
BankATransaction BankATransaction=JsonConvert.DeserializeObject(bankATransJson);
BankA BankA=新BankA();
bankA.Transaction=bankATransaction;
控制台写入线(储蓄银行(bankA));
//输出:
// {
//“银行名称”:“银行”,
//“组名”:“g54321”,
//“ACC_ID”:“A01”,
//“账号”:“A1111”
// }
字符串bankBInputJson=GetBankBTestJsonInput();
BankBTransaction bankBTransInput=JsonConvert.DeserializeObject(bankBInputJson);
BankB BankB=新的BankB();
bankB.Transaction=bankBTransInput;
控制台写入线(储蓄银行(bankB));
//输出:
// {
//“银行名称”:“银行B”,
//“附件ID”:“B02”,
//“账号”:“B2222”,
//“名称”:“B银行”
// }
字符串bankCInputJson=GetBankCTestJsonInput();
BankCtTransaction BankCtTransInput=JsonConvert.DeserializeObject(bankCInputJson);
BankC BankC=新BankC();
bankC.Transaction=bankCTransInput;
控制台写入线(储蓄银行(bankC));
//输出:
// {
//“银行名称”:“BankC”,
//“附件ID”:“C03”,
//“账号”:“C3333”,
//“全名”:“C银行”
// }
}
公共静态字符串存储库(IBankData bankData)
{
//调用serialize对象方法时,我们传递BankJsonConverter
string jsonText=JsonConvert.SerializeObject(bankData,Formatting.Indented,new BankJsonConverter());
//本例仅返回JSON文本
//但您可以根据需要实现save逻辑
返回jsonText;
}
私有静态字符串GetBankATestJsonInput()
{
var obj=new{ACC_ID=“A01”,ACCOUNT_NO=“A1111”,GROUPName=“g54321”};
返回JsonConvert.SerializeObject(obj);
}
私有静态字符串GetBankBTestJsonInput()
{
var obj=new{ACC_ID=“B02”,ACCOUNT_NO=“B2222”,Name=“Bank_Of_B”};
返回JsonConvert.SerializeObject(obj);
}
私有静态字符串GetBankCTestJsonInput()
{
var obj=new{ACC_ID=“C03”,ACCOUNT_NO=“c333”,FullName=“C Bank”};
返回JsonConvert.SerializeObject(obj);
}
}
创建两个接口,一个用于元数据(IBankData
),另一个用于银行交易详细信息(IBankTransaction
).IBankData
界面将维护对IBankTransaction
界面的引用。这还应允许您在需要时添加其他银行,例如银行D
public interface IBankData
{
string BankName { get; }
// ... additional bank meta data properties
// ...
IBankTransaction Transaction { get; set; }
}
public interface IBankTransaction
{
[JsonProperty("ACC_ID")]
string AccountId { get; set; }
[JsonProperty("ACCOUNT_NO")]
string AccountNumber { get; set; }
// ... additional shared bank transaction properties
// ...
}
仅供参考,我选择使用JsonProperty
属性来控制JSON键的名称,这允许根据最佳实践命名类属性,而不影响JSON属性名称
接下来,为您将要使用的每个银行实现接口。在每个银行中添加仅适用于每个实现的附加属性,即自