基于 T 和子类确定类型的更好方法
本文关键字:类型 更好 方法 子类 基于 | 更新日期: 2023-09-27 18:36:19
编写一些处理响应和请求的代码。两者都可以是 XML 的形式,也可以是通过转换和序列化创建的 C# 对象的形式。(这是 .NET 2.0)
响应和请求是较大消息类型的基本实现。现在我有GetEligibility和FindCandidates。
下面使用的 Model.MessageModel 类的示例:
public partial class GetEligibilityResponseMessage : ResponseMessage
public partial class ResponseMessage : Message
因为我不想复制我的映射功能,所以我决定使用泛型来简化过程,而且效果很好:
基类代码
public virtual Model.MessageModel.Message MapToModel<T>(XmlDocument xml)
{
V3Mapper mapper = new V3Mapper();
Model.MessageModel.Message message = mapper.MapToDomainModel<T>(xml, Environment) as Model.MessageModel.Message;
return message;
}
public virtual XmlDocument MapToXml<T>(Model.MessageModel.Message message)
{
V3Mapper mapper = new V3Mapper();
XmlDocument xml= mapper.MapToV3Message<T>(message, Environment);
return xml;
}
当我的代码第一次被调用时,它有一个XML文档。我知道这个文档将被映射为一个请求,所以我调用了一个被覆盖的虚拟方法(我认为它很丑陋)。将映射代码保留在库中的原因是不要重复代码,但我发现我正在做我想通过以下方式避免的事情:
获取资格 : 基类
public override Model.MessageModel.Message MapToModel<T>(XmlDocument xml)
{
if(typeof(T).IsAssignableFrom(typeof(GetEligibilityResponseMessage)))
{
return base.MapToModel<GetEligibilityResponseMessage>(xml);
}
else if (typeof(T).IsAssignableFrom(typeof(GetEligibilityRequestMessage)))
{
return base.MapToModel<GetEligibilityRequestMessage>(xml);
}
return null;//because this is a quick code snippet
}
有没有更优雅的方法呢? 我总是知道我是在处理响应还是请求。我想保持功能打开,这样它就不会太紧密地耦合,但同时让它功能强大且快速。
这将由许多不同的消息类型实现,我真的很讨厌复制/粘贴风格的编码,所以一个优雅的解决方案会很棒,但我不确定是否有。(.NET 2.0)
可以使用 MethodInfo.MakeGenericMethod 方法避免在调用泛型方法之前检查类型。下面是一个快速使用示例:
class Program
{
public static void Generic<T>(T toDisplay)
{
Console.WriteLine("'r'nHere it is: {0}", toDisplay);
}
static void Main(string[] args)
{
MethodInfo mi = typeof(Program).GetMethod("Generic");
MethodInfo miConstructed = mi.MakeGenericMethod(typeof(DateTime));
DateTime now = DateTime.Now;
miConstructed.Invoke(null, new object[] { now });
}
}
请注意,我使用了typeof(DateTime),但在您的情况下,您可以将其替换为typeof(T)以实现所需的松散耦合解决方案。
如果只想验证请求和响应类型,可以让基类知道:
public class BaseClass
{
private readonly Type _requestType;
private readonly Type _responseType;
protected BaseClass(Type requestType, Type responseType)
{
_requestType = requestType;
_responseType = responseType;
}
public T MapToModel<T>(XmlDocument xml)
{
if (typeof(T) != _requestType && typeof(T) != _responseType)
throw new InvalidOperationException("Invalid type");
var mapper = new V3Mapper();
return mapper.MapToDomainModel<T>(xml, Environment);
}
}
public GetEligibility : BaseClass
{
public GetEligibility()
: base(typeof(GetEligibilityRequestMessage), typeof(GetEligibilityResponseMessage))
{}
}
您甚至可以更进一步,使用专用MapToRequest
和知道返回什么的MapToResponse
方法,使BaseClass
通用:
public class BaseClass<TRequest, TResponse>
where TRequest:RequestMessage,
TResponse:ResponseMessage
{
public TRequest MapToRequest(XmlDocument xml)
{ return MapToModel<TRequest>(xml); }
public TResponse MapToResponse(XmlDocument xml)
{ return MapToModel<TResponse>(xml); }
private T MapToModel<T>(XmlDocument xml)
{
var mapper = new V3Mapper();
return mapper.MapToDomainModel<T>(xml, Environment);
}
}
public GetEligibility : BaseClass<GetEligibilityRequestMessage, GetEligibilityResponseMessage>
{}