繁体   English   中英

如何将列表转换<A>为列表</a>

[英]How to cast List<A> to List<B>

如何将List<SelectVacancyDetails_Result>List< SelectVacancyDetails_ResultExtend> ,其中类SelectVacancyDetails_ResultExtend继承自类SelectVacancyDetails_Result

我在下面尝试过但没有运气

   List<SelectVacancyDetails_ResultExtend> vacExtList = vacList.Cast<SelectVacancyDetails_ResultExtend>().ToList();

(基本上我想复制所有列表属性值)

如果所有元素实际上都是SelectVacancyDetails_Result类型(而不是SelectVacancyDetails_ResultExtend ),那么您就不能进行SelectVacancyDetails_ResultExtend 最简单的方法是在SelectVacancyDetails_ResultExtend创建一个构造函数,该构造函数复制属性-或仅使用合成而不是继承(然后可能使用),然后可以使用:

var vacExtList = vacList.Select(vac => new SelectVacancyDetails_ResultExtend(vac))
                        .ToList();

继承不能那样工作。 使用class Derived : Base ,无法将运行时类型为 Base的对象“投射”到Derived 您需要手动复制所有属性或使用类似AutoMapper的属性。

List<SelectVacancyDetails_ResultExtend> vacExtList = vacList.Select(x => (SelectVacancyDetails_ResultExtend)x).ToList();

如前所述,您无法执行此操作:

SelectVacancyDetails_ResultExtend继承SelectVacancyDetails_Result

这样就不SelectVacancyDetails_Result类型为SelectVacancyDetails_ResultExtend的对象转换为类型为SelectVacancyDetails_Result的对象。

您可以将SelectVacancyDetails_ResultExtend转换为SelectVacancyDetails_Result类型,但不能采用其他方式。

您将需要将属性投影到基类项目的列表中:

var vacExtList = vacList.Select(v => new SelectVacancyDetails_ResultExtend() {
   PropertyA = v.PropertyA,
   ...
});

我还要指出,需要这样做有点代码味道-继承链有问题。

如果堆栈项目的解决方案不起作用,则可能是因为其中一项无法投射。 (也许这是一个不太具体的类型的实例)

您可以做的只是获取可以转换的元素,并使用以下代码:

var vacExtList = vacList.OfType<SelectVacancyDetails_ResultExtend>();

编辑

显然,此解决方案假定SelectVacancyDetails_ResultExtend继承自SelectVacancyDetails_Result。

这不可能。 但是,您可以尝试以下解决方案:

 class Program
{
    static void Main(string[] args)
    {
        var vacancies = new List<Vacancy>
        {
            new Vacancy {Id = 1, Details = "flat"},
            new Vacancy {Id = 2, Details = "restaurant"}
        };


        List<VacancyExtended> vacanciesExtended = vacancies.Select(p => new VacancyExtended(p)).ToList();


        foreach (var v in vacanciesExtended)
        {
            Console.WriteLine(v.Details);

        }
        Console.ReadKey();
    }
}


public class Vacancy
{
    public int Id { get; set; }
    public string Details { get; set; }

    public Vacancy(){ }
    public Vacancy(Vacancy vacancy)
    {
        Id = vacancy.Id;
        Details = vacancy.Details;
    }
}
public class VacancyExtended : Vacancy
{
    public VacancyExtended(Vacancy vacancy) : base(vacancy)
    {

    }

    public string AdditionalInfo { get; set; }
}

这是一个典型的问题。 然后在派生类或第3方库(如AutoMapper使用构造函数,您还可以使用Reflection创建自定义扩展方法,它的速度要慢得多,因此如果您遇到某种瓶颈时就不要使用它,并且只能使用它如果性能并不是您并不真正担心的东西,或者您无法修改派生类并且由于某种原因不想使用AutoMapper 这些示例仅涵盖具有属性(无字段)的典型EF模型。

所以方法是:

public static class Helper
{
    public static IEnumerable<T2> ConvertRange<T1, T2>(this IEnumerable<T1> collection)
        where T1 : class
        where T2 : class, new()
    {
        List<T2> elements = new List<T2>();

        PropertyInfo[] propsT2 = typeof(T2).GetProperties();
        PropertyInfo[] propsT1 = typeof(T1).GetProperties()
            .Where(p => propsT2.Any(p2 => p2.Name == p.Name)).ToArray();

        propsT1.OrderBy(p => p.Name);
        propsT2.OrderBy(p => p.Name);

        foreach (T1 item in collection)
        {
            T2 newEl = new T2();

            for (int i = 0; i < propsT1.Length; i++)
                propsT2[i].SetValue(newEl, propsT1[i].GetValue(item));

            elements.Add(newEl);
        }

        return elements;
    }
}

范例:

    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    class Manager
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    static void Main(string[] args)
    {
        List<Person> ps = new List<Person>()
        {
            new Person() { Name ="Alex", Age = 30 },
            new Person() { Name ="Michael", Age = 22 }
        };

        List<Manager> mgr = ps.ConvertRange<Person, Manager>().ToList();

        foreach (var item in mgr)
            Console.WriteLine(item.Name + "   " + item.Age);

        Console.ReadKey();
   }

}

输出:

Alex     30
Michael  22

这是使用AutoMapper的示例

private static void Main(string[] args)
{
    Mapper.CreateMap<Foo, FooBar>();

    List<Foo> randomFoos = new List<Foo>();

    for (int i = 0; i < 10; i++)
    {
        randomFoos.Add(new Foo());
    }

    Console.WriteLine("### Random foos");
    randomFoos.ForEach(Console.WriteLine);

    Console.WriteLine("### Converted foos");
    Mapper.Map<List<FooBar>>(randomFoos)
            .ForEach(Console.WriteLine);
}

public class Foo
{
    public Foo()
    {
        this.Id = Guid.NewGuid().ToString();
        this.Name = Guid.NewGuid().ToString("n")
                        .Substring(6);
    }

    public string Id { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        StringBuilder builder = new StringBuilder();
        this.GetType()
            .GetProperties()
            .ToList()
            .ForEach(property => builder.AppendLine(string.Format("{0}: {1}", property.Name, property.GetValue(this))));

        builder.AppendLine();

        return builder.ToString();
    }
}

public class FooBar : Foo
{
    public FooBar()
    {
        this.Description = Guid.NewGuid().ToString()
                                .Substring(12);
    }

    public string Description { get; set; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM