【发布时间】:2020-06-07 08:35:39
【问题描述】:
我想创建一个类来调用我的 SQL Server 中的存储过程。我将 C# 与 .NET Core 3.1 一起使用。所有存储过程都返回相同的结果,但在某些情况下,我必须做更多的活动,然后每个函数都有自己的基于基类的返回类型,在下面的代码中称为 BaseResponse。
public class BaseResponse
{
public int ErrorCode { get; set; }
public string Message { get; set; }
}
public class InvoiceResponse : BaseResponse
{
public bool IsPaid { get; set; }
}
然后,我有我的BaseCall,它负责调用存储过程并返回BaseResponse。
public async Task<BaseResponse> BaseCall(string procedureName, string[] params)
{
BaseResponse rtn = new BaseResponse();
// call SQL Server stored procedure
return rtn;
}
在另一个类中,我想将 BaseResponse 与派生类一起转换。为此,我认为我可以将 BaseResponse 与派生类一起转换,但我错了。
public async Task<InvoiceResponse> GetInvoice(int id)
{
InvoiceResponse rtn = new InvoiceResponse();
BaseResponse response = BaseCall("myprocedure", null);
rtn = (InvoiceResponse)response;
// do something else
return rtn;
}
我看到了另外两个帖子(Convert base class to derived class 和 this one),我明白我不能按照我想要的方式投射。然后我就是我的延伸
/// <summary>
/// Class BaseClassConvert.
/// </summary>
public static class BaseClassConvert
{
/// <summary>
/// Maps to new object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sourceobject">The sourceobject.</param>
/// <returns>T.</returns>
/// <remarks>
/// The target object is created on the fly and the target type
/// must have a parameterless constructor (either compiler-generated or explicit)
/// </remarks>
public static T MapToNewObject<T>(this object sourceobject) where T : new()
{
// create an instance of the target class
T targetobject = (T)Activator.CreateInstance(typeof(T));
// map the source properties to the target object
MapToExistingObject(sourceobject, targetobject);
return targetobject;
}
/// <summary>
/// Maps to existing object.
/// </summary>
/// <param name="sourceobject">The sourceobject.</param>
/// <param name="targetobject">The targetobject.</param>
/// <remarks>The target object is created beforehand and passed in</remarks>
public static void MapToExistingObject(this object sourceobject, object targetobject)
{
// get the list of properties available in source class
var sourceproperties = sourceobject.GetType().GetProperties().ToList();
// loop through source object properties
sourceproperties.ForEach(sourceproperty =>
{
var targetProp = targetobject.GetType().GetProperty(sourceproperty.Name);
// check whether that property is present in target class and is writeable
if (targetProp != null && targetProp.CanWrite)
{
// if present get the value and map it
var value = sourceobject.GetType().GetProperty(sourceproperty.Name).GetValue(sourceobject, null);
targetobject.GetType().GetProperty(sourceproperty.Name).SetValue(targetobject, value, null);
}
});
}
}
此代码有效,我可以像这样使用它:
public async Task<InvoiceResponse> GetInvoice(int id)
{
InvoiceResponse rtn = new InvoiceResponse();
BaseResponse response = BaseCall("myprocedure", null);
response.MapToExistingObject(rtn);
// do something else
return rtn;
}
我的问题是:
- 在 .NET Core 中是否有更有效的方法将基类转换为派生类?
- 这是铸造的最佳做法吗?
- 还有其他指南吗?
- 此过程使用
Reflection。从性能的角度来看,这是实现此演员阵容的正确且最便宜的方式吗?
【问题讨论】:
-
我对这个前提感到困惑。如果
BaseCall不知道派生类型(它似乎并不知道),那么它甚至无法传递来自存储过程的信息,这些信息将允许稍后构造更多派生类型。如果它确实知道它们,那么它可以立即构建它们。而且,如果不需要额外信息来构造派生类型,那么您可以简单地在所有接受基类型实例并从中复制的派生类型上使用构造函数。 -
也可能是the case,您不想为数据库响应提供自己的类并使用实体框架等 ORM 框架。
-
我没有得到你的评论。
BaseCall是一个调用存储过程并从它们接收结果的类。谁在调用BaseClass具有基于BaseResponse以及其他一些字段的自己的返回类型。我不想使用AutoMapper(例如)将每个字段从BaseResponse映射到派生类。 -
我使用
Entity Framework调用存储过程并获取结果。 -
Who is calling the BaseClass has its own return type based on the BaseResponse plus some other fields- 如果BaseResponse没有从数据库中返回这些其他字段,那么调用者将如何获取这些字段?
标签: c# .net-core base-class .net-core-3.1