在C#中将Base类转换为Derived类?

时间:2014-05-08 14:21:16

标签: c# asp.net-mvc-5

我正在尝试将Base类转换为派生类对象。看下面的代码,转换时我遇到了问题。这是基本的事情,但苦苦挣扎。

[HttpGet]
[Route("/Edit/{Id}")]
public ActionResult Edit(int Id)
{

    List<ClassA> Data = Ctx.GetClassAFromId(Id);

    // Now Here I want convert ABC List<ClassA> to XyZ List<ClassA>
    //How to do that?
    return View(DataXYZ);
}

由EF

生成的模型
namespace ABC
{

    public partial class ClassA
    {
           public string First_name { get; set; }
           public string Last_Name { get; set; }
    }
}

项目模型

namespace XYZ
{
    [MetadataType(typeof(ClassAMetadata))]
    public partial class ClassA:ABC.ClassA
    {

    }   

    public class ClassAMetadata
    {
        [DisplayName(@"First Name")]
        [Required]
        public string First_name { get; set; }


        [DisplayName(@"Last Name")] 
        [Required]       
        public string Last_Name { get; set; }
    }
}

如何将ABC.ClassA转换为XYZ.ClassA?

编辑:

我们正在开发i18n项目。所以我们需要以不同的语言显示每个文本。但我们的EF项目在不同的Namespace中,而web项目则在不同的Namespace中。这就是我从基类派生的原因

4 个答案:

答案 0 :(得分:0)

即使他们的名字相似,但他们的课程完全不同。它就像你打电话给他们FooBar

一样

您需要一个转换这些对象的方法。它将Foo对象作为参数,然后返回等效的Bar对象

public Bar Foo_To_Bar(Foo myFoo)
{
    return new Bar() { Prop1 = myFoo.Prop1, Prop2 = myFoo.Prop2 };
}

这样的事情。如果你想在两个方向进行转换,你可能还需要一种相反的方法。

注意:如果类具有相同名称的属性,我建议您查看Automapper。它可以为您自动完成大部分无聊的工作。

修改
显然,您的Foo继承自Bar。这使事情复杂化了一些。当我有空的时候,我会重复这个答案。

我没有看到使用ViewModel(XYZ.ClassA)派生自您的基本实体(ABC.ClassA)的用例。你能解释一下为什么需要吗?我觉得你在这里滥用继承权。

一般来说,您希望XYZ.ClassA拥有ABC.ClassA类型的属性(或任何IEnumerable<ABC.ClassA>变体),而不是从中继承。

您能否确认这是否是实际要求,或者可以成为问题的一部分,如果它解决了您的问题,可以更改吗?

答案 1 :(得分:0)

您无法将List<BaseClass>转换为List<DerivedClass>

你可以做的是使用linq:

listABC.Cast<XYZ.ClassA>.ToList()

但是了望 - 这是O(n)程序

答案 2 :(得分:0)

编辑 - 基于一个对象从另一个继承的事实,请参阅C#/.NET Little Wonders: Use Cast() and OfType() to Change Sequence Type


几个选项:

1

namespace ABC
{

    public partial class ClassA
    {
           public ClassA(XYZ.ClassA classToConvert)
           {
             this.First_name = classToConvert.First_name,
             this.Last_Name = classToConvert.Last_Name
           }

           public string First_name { get; set; }
           public string Last_Name { get; set; }
    }
}

单独使用:

 var newClassA = new ABC.ClassA((XYZ.ClassA)classA)

在列表中执行:

 List<ABC.ClassA> newClassAList = classAList.Select(p => new ABC.ClassA((XYZ.ClassA)p).ToList();

或者在没有上述构造函数且使用对象初始化程序的列表中执行此操作

 List<ABC.ClassA> newClassAList = classAList.Select(p => new ABC.ClassA{First_name = p.First_name, Last_Name = p.Last_Name}.ToList();
  1. 正如其他人提到的那样使用AutoMapper。

    • 使用Nuget并将AutoMapper添加到您的项目(以及一些初始化代码)
    • 创建地图:

      Mapper.CreateMap<XYZ.ClassA, ABC.ClassA>();
      
    • 映射您的对象:

      var myABCClassA= Mapper.Map<XYZ.ClassA, ABC.ClassA>(myXYZClassA);
      
    • 只要两个类上的属性名称与您需要的所有代码相匹配

答案 3 :(得分:0)

我今天创建了这个

public static void Map<T1, T2>(this T1 obj1, T2 obj2) where T1 : class where T2 : class
{
    IEnumerable<(PropertyInfo p1, PropertyInfo p2)> properties = typeof(T1).GetProperties()
        .Join(typeof(T2).GetProperties(), o => o.Name, t => t.Name, (o, t) => (o, t));
    foreach((PropertyInfo p1, PropertyInfo p2) in properties)
    {
        if (p1.CanWrite && p1.PropertyType == p2.PropertyType)
        {
            p1.SetValue(obj1, p2.GetValue(obj2));
        }
    }
}