我将如何处理除了名称之外完全相同的两个类



我正在Core 3.1中编写一个服务。在我正在编写的服务中,我创建了一个连接到遗留SOAP服务的服务,该服务与一个更旧的系统接口。SOAP服务提供基本的CRUD操作,并使用类作为数据容器。问题是,为服务引用生成的代码为具有完全相同属性的对象创建了单独的partial类。

public partial class REQUEST1
{
public string PropertyName {get; set;}
}
public partial class REQUEST2
{
public string PropertyName {get; set;}
}

我发现,在准备请求对象方面,我正在一遍又一遍地编写相同的代码。

private void SetProperties(MyClass parameters, REQUEST1 request)
{
request.PropertyName = parameters.MyParamValue;
}
private void SetProperties(MyClass parameters, REQUEST2 request)
{
request.PropertyName = parameters.MyParamValue;
}

我不想修改生成的代码,因为下次生成代码时,必须有人记得这样做。接口和基类并不是一个真正的选项,因为这是修改生成的代码。因此,我正在寻找关于如何编写一个方法的建议,该方法可以采用其中一个类并设置值,而无需编写千篇一律的代码。

更新:所以这变得更加复杂。在创建/更新服务中,我有复杂的对象。

public partial class ADDRESS
{
// Address Properties created by the service reference
}
public partial class PERSON
{
ADDRESS[] ADDRESSES { get; set;}
// Other properties created by the service reference
}

我可以为地址和人员创建接口,但这会产生另一个问题。

public interface IAddress
{
// Address properties 
}
public interface IPerson
{
IAddress[] ADDRESSES {get;set;}
// Other properties
}
public partial class ADDRESS : IAddress
{
}
public partial class PERSON : IPerson
{
}

这会创建一个错误,说明PERSON没有实现成员IAddress[]ADDRESSES,因为它没有正确的返回类型。这是有道理的,但我不确定如何绕过它。对于具有基元类型的单个对象,这种方法有效,但对于更复杂的类型,似乎需要另一种解决方案。

我建议使用分部类为类添加一个接口。

public interface IRequest
{
string PropertyName {get; set;}
}
public partial class REQUEST1
{
public string PropertyName {get; set;}
}
public partial class REQUEST2
{
public string PropertyName {get; set;}
}
public partial class REQUEST1 : IRequest
{
}
public partial class REQUEST2 : IRequest
{
}

你可以有一个像这样的方法

private void SetProperties(MyClass parameters, IRequest request)
{
request.PropertyName = parameters.MyParamValue;
}

如果你不想手工完成。。。。。。。。。考虑

https://automapper.org/

https://www.nuget.org/packages/automapper/

示例(当属性名称重叠时非常容易(

MapperConfigurationconfig = new MapperConfiguration(cfg => {
cfg.CreateMap<Request1, Request2>();
});
IMapper iMapper = config.CreateMapper();
Request1 source = new Request1();
Request2 destination = iMapper.Map<Request1, Request2>(source);

如果属性名称不完全匹配。。。。。您调整";config";。

这是另一篇文章:

https://www.infoworld.com/article/3192900/how-to-work-with-automapper-in-csharp.html

如果你不想在代码生成中深入挖掘并添加接口或子类,也许扩展方法可以做到这一点(文档(结合一点反射:(其他SO答案

在您的情况下:

public static class RequestExtensions 
{
public static void SetProperty(this REQUEST1 request, YourClass parameters)
{
SetProperty(request, "PropertyName", parameters.MyParamValue;
}
public static void SetProperty(this object obj, string propertyName, object value)
{
// Very generic. Always try to not use reflection :)
// No exception handling or null checks here because of example code.
obj.GetType().InvokeMember(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, Type.DefaultBinder, obj, value);
}
}

在这里,您可以看到您可以将扩展方法添加到已经生成的类中。另一种选择是直接使用SetProperty(不推荐(。

在我看来,最好的解决方案是在生成器中深入挖掘,并添加接口或基类,以支持以所有其他方式对类进行通用访问。反射是你最好的朋友。

最新更新