铸造通用对象的方法c#

时间:2016-02-25 07:59:09

标签: c# generics casting

我有几个具有相同属性的对象的对象。

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

4 个答案:

答案 0 :(得分:5)

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

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等库可以帮助您解决这个问题。

AutoMapper.Mapper.CreateMap<Source1, Destination1>();
var destItem = AutoMapper.Mapper.Map<Destination1 >(sourceItem);

答案 1 :(得分:1)

作为Magnus points out,如果您想实际投射,接口是您的选择。但是,我认为你可能实际上在考虑转换而不是转换。

我会考虑检查Automapper,因为它确实存在 来自documentation

var source = new Source<int> { Value = 10 };  
var dest = mapper.Map<Source<int>, Destination<int>>(source);  
dest.Value.ShouldEqual(10);

您可以通过命名约定(甚至自定义命名约定),自定义映射器或两者的组合来配置两种类型之间的映射。我见过的最常见的用例是将datatransfer对象映射到模型,然后再返回。

如果一个对象基本上是具有一些额外逻辑和属性的另一个对象,那么Decorator pattern可能就是你要找的东西。在这里,您基本上用一些额外的东西包装(装饰)一个对象,装饰对象将所有东西链接到原始对象。

答案 2 :(得分:0)

Boris Calens pointed out 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;
}

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

My answer to this question(您可能会觉得有帮助)显示了一个类似的示例,比较属性字段。

答案 3 :(得分:-2)

我使用这种从httpWebResponse解析Json对象的通用方法,可能是你可以使用它来让你的工作。

UIGraphicsGetCurrentContext()

希望它能引导你朝着正确的方向前进。 =)