强制转换泛型对象 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;
}

强制转换泛型对象 c# 的方法

这里最好的选择是引入一个通用接口(或基类)。没有其他方法可以将一个项目转换为另一个项目。

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;
}

您还可以轻松遍历相应类型的属性;指定绑定标志以过滤要复制的字段/属性;并扩展比较以确定两个成员是否属于同一类型(即检查一种类型是否派生自另一种类型)。

我对这个问题的回答(您可能也会觉得有帮助)展示了一个类似的例子,比较属性字段。