Reputation: 768
I have three classes A, B, Common.
public class A
{
public int Id { get; set; }
public string Name { get; set; }
}
public class B
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Common
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
I want to put all A and B into a collection of Common
var result = new List<Common>();
foreach (var i in A_collection) {
result.Add(new Common() {
Id = i.Id,
Name = i.Name,
Type = "This is A"
});
}
foreach (var i in B_collection) {
result.Add(new Common() {
Id = i.Id,
Name = i.Name,
Type = "This is B"
});
}
Please notice that I cannot modify any code in class A, B and Common. But I can add new classes
Is there a way to use generics to simplify the code to just use one loop like this?
foreach (var i in T_collection) {
result.Add(new Common() {
Id = i.Id,
Name = i.Name,
Type = "This is T"
});
}
Upvotes: 0
Views: 132
Reputation: 74605
I think I'd just write an extension method pair:
public static Common AsCommon(this A a)
{
return new Common()
{
Id = a.Id,
Name = a.Name,
Type = "This is A"
};
}
public static Common AsCommon(this B b)
{
return new Common()
{
Id = b.Id,
Name = b.Name,
Type = "This is B"
};
}
And then e.g.:
listOfCommon.AddRange(listOfA.Select(AsCommon));
Or e.g.:
listOfCommon = listOfA.Select(AsCommon).Concat(listOfB.Select(AsCommon)).ToList();
Probably also worth pointing out that using AutoMapper can save you the hassle of writing code to copy an A or B to a new Common, because automapper can be set up to understand A->Common and then copy the matching property names. With some extra config it can also copy mismatched properties
Upvotes: 0
Reputation: 999
Not impossible in technical terms. First you write methods to create Common
from object
...
public static Common GenerateCommon(object o)
{
if (o is A)
{
return GenerateCommon(o as A);
}
if (o is B)
{
return GenerateCommon(o as B);
}
throw new Exception("Object is neither A nor B");
}
public static Common GenerateCommon(A a)
{
return new Common()
{
Id = a.Id,
Name = a.Name,
Type = "This is A"
};
}
public static Common GenerateCommon(B b)
{
return new Common()
{
Id = b.Id,
Name = b.Name,
Type = "This is B"
};
}
Then concatenate two lists as list of object
s.
List<A> alist = new List<A>();
alist.Add(new A() { Id = 1, Name = "asd" });
alist.Add(new A() { Id = 2, Name = "2dd" });
alist.Add(new A() { Id = 3, Name = "3q" });
List<B> blist = new List<B>();
blist.Add(new B() { Id = 4, Name = "4asd" });
blist.Add(new B() { Id = 5, Name = "5dd" });
blist.Add(new B() { Id = 6, Name = "63q" });
List<object> olist = alist.Select(x => (object)x).ToList();
olist.AddRange(blist.Select(x => (object)x));
List<Common> clist = new List<Common>();
foreach(var o in olist)
{
clist.Add(GenerateCommon(o));
}
But I think modifying A/B/Common or following @T.S.'s answer is better.
Upvotes: 0
Reputation: 584
If your use case allows you to use interface in the places of the objects, and A and B are not sealed class, then you can wrap A and B in your own class with an interface. Something like this:
public interface ICommon
{
int Id { get; set; }
string Name { get; set; }
}
public class MyA : A, ICommon {}
public class MyB : B, ICommon {}
then instead of creating new instances of A
or B
, you can create instances of MyA
and MyB
, which will allow you to work with ICommon
while still being interchangeable for A
or B
, or wherever you declare objects of A
or B
, just replace them with MyA
or MyB
.
Upvotes: 4
Reputation: 19330
Use LINQ?
var lA = new List<A>();
var lB = new List<B>();
var a = lA.Select(a => new Common(){ Id = a.Id, Name = a.Name, Type = "This is A"});
var b = lB.Select(b => new Common(){ Id = b.Id, Name = b.Name, Type = "This is B"});
var all = a.Append(b).ToList();
Upvotes: 2