我想创建一个类来调用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;
}
我的问题是:
Reflection
。从性能的角度来看,这是实现此演员表的正确且最便宜的方法吗?您不能cast(不会出错)将表达式返回/包含基类实例给任何继承者(如果该实例实际上没有继承)。强制转换为docs状态是编译器试图在运行时执行显式转换的尝试。另外,正如您提到的,您不能实现自定义类或自定义类的自定义显式转换。您正在寻找的是映射,并且为此提供了很多库,例如但不限于Automapper,Mapster或ExpressMapper。