强制转换泛型对象 c# 的方法
本文关键字:方法 对象 泛型 转换 | 更新日期: 2023-09-27 18:36:04
我有几个对象,它们有一个具有相同属性的相应对象。
class Source1
{
int id;
string name;
DateTime date;
}
class Destination1
{
int id;
string name;
DateTime date;
}
class Source2
{
int id;
string code;
double price;
}
class Destination2
{
int id;
string code;
double price;
}
现在我想创建一个具有泛型类型的方法,该方法可以将对象强制转换为相应的对象。
public TDestination Cast<TSource, TDestination>(TSource source)
{
//TDestination destination = (TDestination) source;
return destination;
}
这里最好的选择是引入一个通用接口(或基类)。没有其他方法可以将一个项目转换为另一个项目。
public interface IItem
{
int id {get;set;}
string name {get;set;}
DateTime date {get;set;}
}
class Source1 : IItem
{
public int id {get;set;}
public string name {get;set;}
public DateTime date {get;set;}
}
class Destination1 : IItem
{
public int id {get;set;}
public string name {get;set;}
public DateTime date {get;set;}
}
然后,只需将对象强制转换为接口并访问属性即可。
var item1 = (IItem)sourceItem;
var item2 = (IItem)destinationItem;
如果您不想这样做,另一种选择是使用反射来遍历源中的属性并创建目标类型的新对象,并尝试使用共享名称映射属性。但是,这将创建一个新对象,并且与强制转换完全不同。有一些库,如自动映射器可以帮助你解决这个问题。
AutoMapper.Mapper.CreateMap<Source1, Destination1>();
var destItem = AutoMapper.Mapper.Map<Destination1 >(sourceItem);
正如Magnus指出的那样,如果你想真正投射,接口是你的路。但是,我想您可能实际上正在考虑转换而不是铸造。
我会考虑检查自动映射器,因为它确实存在。
从文档中:
var source = new Source<int> { Value = 10 };
var dest = mapper.Map<Source<int>, Destination<int>>(source);
dest.Value.ShouldEqual(10);
您可以通过命名约定(甚至是自定义命名约定)、自定义映射器或两者的组合来配置两种类型之间的映射。我见过的最常见的用例是将数据传输对象映射到模型并再次返回。
如果一个对象基本上是具有一些额外逻辑和属性的另一个对象,则装饰器模式可能是您要查找的。在这里,你基本上用一些额外的东西包裹(装饰)一个对象,装饰对象将所有内容链接到原始对象。
Boris Calens指出了Automapper,这很棒,但是如果你想避免使用外部代码,一个针对你的示例问题的自制解决方案非常简单:
using System.Reflection;
...
TDestination Copy<TSource, TDestination>(TSource source)
where TDestination : new()
{
TDestination dest = new TDestination();
foreach (FieldInfo srcField in typeof(TSource).GetFields())
{
foreach (FieldInfo destField in typeof(TDestination).GetFields())
{
if (destField.Name == srcField.Name && destField.FieldType == srcField.FieldType)
{
destField.SetValue(dest, srcField.GetValue(source));
}
}
}
return dest;
}
您还可以轻松遍历相应类型的属性;指定绑定标志以过滤要复制的字段/属性;并扩展比较以确定两个成员是否属于同一类型(即检查一种类型是否派生自另一种类型)。
我对这个问题的回答(您可能也会觉得有帮助)展示了一个类似的例子,比较属性和字段。