Reputation: 75
How do I cast List<SelectVacancyDetails_Result>
to List< SelectVacancyDetails_ResultExtend>
where class SelectVacancyDetails_ResultExtend
is inherited from class SelectVacancyDetails_Result
.
I tried below but no luck
List<SelectVacancyDetails_ResultExtend> vacExtList = vacList.Cast<SelectVacancyDetails_ResultExtend>().ToList();
(Basically i want all list properties value to be copied over)
Upvotes: 1
Views: 304
Reputation: 15294
Here's an example using 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; }
}
Upvotes: 0
Reputation: 13676
It's a typical problem. Other then use constructor in your derived class or 3rd party libs like AutoMapper
you can also create your custom extension method with Reflection
it'd much slower so don't use it if you're working with in bottleneck of some sort and use it only if performance is not something that you aren't really worry about or if you can't modify your derived class and by some reason don't want to use AutoMapper
. These example covers only typical EF models with properties (no fields).
So the method is :
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;
}
}
Example :
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();
}
}
Output :
Alex 30
Michael 22
Upvotes: 0
Reputation: 1916
It is not possible. However you can try this solution:
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; }
}
Upvotes: 0
Reputation: 2509
If stack item's solution doesn't work, it's perfhaps because one of the item can't be casted. (Maybe it's an instance of a less specific type)
what you could do is only get the element that could be casted, and use the following code:
var vacExtList = vacList.OfType<SelectVacancyDetails_ResultExtend>();
EDIT:
This solution assumes that SelectVacancyDetails_ResultExtend inherits from SelectVacancyDetails_Result, obviously.
Upvotes: 0
Reputation: 115779
Inheritance does not work that way. With class Derived : Base
, it is not possible to "cast" an object with runtime type Base
to Derived
. You'll need to either copy all properties manually or use something like AutoMapper.
Upvotes: 1
Reputation: 33867
You can't do this, if as you have stated:
SelectVacancyDetails_ResultExtend
inherits SelectVacancyDetails_Result
Then you can't cast an object of type SelectVacancyDetails_Result
to type SelectVacancyDetails_ResultExtend
.
You can cast SelectVacancyDetails_ResultExtend
to type SelectVacancyDetails_Result
, but not the other way.
You will need to project your properties into the list of base class items instead:
var vacExtList = vacList.Select(v => new SelectVacancyDetails_ResultExtend() {
PropertyA = v.PropertyA,
...
});
I would also note that having a need to do this is a bit of a code smell - there is something wrong with your inheritance chain.
Upvotes: 0
Reputation: 1500923
If all the elements are actually of type SelectVacancyDetails_Result
(not SelectVacancyDetails_ResultExtend
) then you can't just cast. The simplest approach would be to create a constructor in SelectVacancyDetails_ResultExtend
which copied the properties - or just used composition instead of inheritance, potentially - and then you can use:
var vacExtList = vacList.Select(vac => new SelectVacancyDetails_ResultExtend(vac))
.ToList();
Upvotes: 7
Reputation: 564
List<SelectVacancyDetails_ResultExtend> vacExtList = vacList.Select(x => (SelectVacancyDetails_ResultExtend)x).ToList();
Upvotes: 0