I have a List<TerminalLink> from which I want to retrieve a subset of. See the class structure below.
The subset is defined by a "map" which identifies which ChannelLink to select in any given scenario. Multiple ChannelLinks may be required per scenario, perhaps from the same ChannelGroup, perhaps from different ChannelGroups on the same TerminalLink, and perhaps from multiple TerminalLinks in my original in memory list.
The ChannelLink can only be select if it's ChannelGroupLink and TerminalLink match too (they form part of the index, I guess).
I have tried various Linq and foreach approaches, but I'm running into tens of lines of code, which is ugly and difficult to follow. I'm sure there is an elegant approach.
How do I return a pruned List<TerminalLink> containing just the data that matches my map (i.e. containing only TerminalLinks and ChannelGroupLinks with required ChannelLinks)?
Class structure:
public class TerminalLink
{
public string TerminalName { get; set; }
public string TerminalType { get; set; }
public ChannelGroupLink[] ChannelGroups { get; set; }
}
public class ChannelGroupLink
{
public string GroupName { get; set; }
public int ItemType { get; set; }
public int SubType { get; set; }
public ChannelLink[] Channels { get; set; }
}
public class ChannelLink
{
public string ChannelName { get; set; }
public string PathName { get; set; }
public string DataType { get; set; }
public bool IsOutput { get; set; }
}
EDIT to include the latest attempt:
public static List<TerminalLink> GetCompatibleChannelLinks(List<TerminalLinkMap> terminalLinkMaps, List<TerminalLink> asBuiltList)
{
List<TerminalLink> matching = new List<TerminalLink>();
var terminalsWithSomeMatchingChannelGroups = from terminal in asBuiltList
from tlm in terminalLinkMaps
where terminal.TerminalType == tlm.ItemSubTypeName
from cgsMaps in tlm.ChannelGroupsToLink
from cgs in terminal.ChannelGroups
where cgsMaps.IsLinkMatch(cgs.GroupName, cgs.ItemType, cgs.SubType)
select (
link: new TerminalLink()
{
TerminalName = terminal.TerminalName,
TerminalType = terminal.TerminalType
},
original: terminal, map: tlm
);
foreach (var possibleLink in terminalsWithSomeMatchingChannelGroups)
{
var linkCandidate = possibleLink.link;
var originalData = possibleLink.original;
var map = possibleLink.map;
foreach (var cgs in originalData.ChannelGroups)
{
foreach (var channel in cgs.Channels)
{
// WIP
}
}
}
}
EDIT 2: inclusion of TeminalLinkMap
public class TerminalLinkMap
{
public string TerminalTypeName { get; set; }
public string ItemSubTypeName { get; set; } // Match on this.
public ChannelGroupToLink[] ChannelGroupsToLink { get; set; }
}
public class ChannelGroupToLink
{
public string GroupName { get; set; } // regex match is ok.
public int ItemType { get; set; }
public int SubType { get; set; }
public ChannelToLink[] Channels { get; set; }
public ChannelGroupToLink GetClone() => GetClone(this);
public bool IsLinkMatch(string groupName, int itemType, int subType)
{
return
GroupName == groupName
&& ItemType == itemType
&& SubType == subType;
}
}
public class ChannelToLink
{
public int ItemType { get; set; }
public string DataType { get; set; }
public int DataSizeInBits { get; set; }
public bool IsOutput { get; set; }
public ChannelToLink GetClone() => GetClone(this);
public bool IsLinkMatch(string dataType, bool isOutput)
{
return
DataType == dataType
&& IsOutput == isOutput;
}
public static ChannelToLink GetClone(ChannelToLink original) => new ChannelToLink()
{
ItemType = original.ItemType,
DataType = original.DataType,
DataSizeInBits = original.DataSizeInBits,
IsOutput = original.IsOutput
};
}
There is no need for a join.
Try following:
class Program
{
static void Main(string[] args)
{
List<TerminalLink> asBuiltList = new List<TerminalLink>();
List<TerminalLink> links = asBuiltList
.Select(x => new { TerminalLink = x, ChannelGroups = x.ChannelGroups.Where(y => y.IsLinkMatch("Apple", 123, 456)) })
.Where(x => x.ChannelGroups.Count() > 0)
.Select(x => new TerminalLink() { TerminalName = x.TerminalLink.TerminalName, TerminalType = x.TerminalLink.TerminalType, ChannelGroups = x.ChannelGroups.ToArray()})
.ToList();
}
}
public class TerminalLink
{
public string TerminalName { get; set; }
public string TerminalType { get; set; }
public ChannelGroupLink[] ChannelGroups { get; set; }
}
public class ChannelGroupLink
{
public string GroupName { get; set; }
public int ItemType { get; set; }
public int SubType { get; set; }
public ChannelLink[] Channels { get; set; }
public Boolean IsLinkMatch(string groupName, int itemType, int subType)
{
return (this.GroupName == groupName) && ( this.ItemType == itemType) && (this.SubType == subType);
}
}
public class ChannelLink
{
public string ChannelName { get; set; }
public string PathName { get; set; }
public string DataType { get; set; }
public bool IsOutput { get; set; }
}
}
Related
Hi all i have two classes and i have two methods where i am passing these two classes into methods individually and checking name and NarrativeHTML and rendering bulleted list.
public class LibraryHydronicEquipment : AEIMasterBase
{
public string Name { get; set; }
public HydronicEquipmentType? Type { get; set; }
[Column(TypeName = "jsonb")]
public List<HydronicSystemType> Systems { get; set; }
[Column(TypeName = "jsonb")]
public List<EquipmentProperty> Properties { get; set; }
public string NarrativeHTML { get; set; }
}
public class LibrarySteamEquipment : AEIMasterBase
{
public string Name { get; set; }
public SteamEquipmentType? Type { get; set; }
[Column(TypeName = "jsonb")]
public List<SteamSystemType> Systems { get; set; }
[Column(TypeName = "jsonb")]
public List<EquipmentProperty> Properties { get; set; }
public string NarrativeHTML { get; set; }
}
Method 1:
private void BuildBulletedList(List<LibraryHydronicEquipment> libraryHydronicEquipments)
{
List<Run> labels = new List<Run>();
foreach (var equipmentItem in libraryHydronicEquipments)
{
if (!string.IsNullOrEmpty(equipmentItem.NarrativeHTML))
{
var htmlRuns = this.DocumentHtmlConverter.Parse(equipmentItem.NarrativeHTML)
.First()
.ChildElements
.Where(c => c is Run)
.Cast<Run>()
.Select(n => n.CloneNode(true));
labels.Add(new Run(htmlRuns));
}
else if (!string.IsNullOrEmpty(equipmentItem.Name))
{
labels.Add(new Run(new Text(equipmentItem.Name)));
}
}
BuildList(labels);
}
Method 2
private void BuildBulletedList(List<LibrarySteamEquipment> librarySteamEquipments)
{
List<Run> labels = new List<Run>();
foreach (var equipmentItem in librarySteamEquipments)
{
if (!string.IsNullOrEmpty(equipmentItem.NarrativeHTML))
{
var htmlRuns = this.DocumentHtmlConverter.Parse(equipmentItem.NarrativeHTML)
.First()
.ChildElements
.Where(c => c is Run)
.Cast<Run>()
.Select(n => n.CloneNode(true));
labels.Add(new Run(htmlRuns));
}
else if (!string.IsNullOrEmpty(equipmentItem.Name))
{
labels.Add(new Run(new Text(equipmentItem.Name)));
}
}
BuildList(labels);
}
and i am calling these methods like as below
if (hydronicSystem.Equipment.Source.Count != 0)
{
BuildBulletedList(hydronicSystem.Equipment.Source);
}
if (steamSystem.Equipment.Source.Count != 0)
{
BuildBulletedList(steamSystem.Equipment.Source);
}
update :
if (hydronicSystem.Equipment.Source.Count != 0)
{
BuildBulletedList(hydronicSystem.Equipment.Source);
}
if (hydronicSystem.Equipment.Distribution.Count != 0)
{
BuildBulletedList(hydronicSystem.Equipment.Distribution);
}
if (hydronicSystem.Equipment.Terminals.Count != 0)
{
BuildBulletedList(hydronicSystem.Equipment.Terminals);
}
Is there any way we can combine these two methods into single generic method?
thanks in advance!!
Move the shared members into a base type
public interface IRender {
string Name { get; set; }
string NarrativeHTML { get; set; }
}
and have the classes derive from that type
public class LibraryHydronicEquipment : AEIMasterBase, IRender {
public string Name { get; set; }
public HydronicEquipmentType? Type { get; set; }
[Column(TypeName = "jsonb")]
public List<HydronicSystemType> Systems { get; set; }
[Column(TypeName = "jsonb")]
public List<EquipmentProperty> Properties { get; set; }
public string NarrativeHTML { get; set; }
}
public class LibrarySteamEquipment : AEIMasterBase, IRender {
public string Name { get; set; }
public SteamEquipmentType? Type { get; set; }
[Column(TypeName = "jsonb")]
public List<SteamSystemType> Systems { get; set; }
[Column(TypeName = "jsonb")]
public List<EquipmentProperty> Properties { get; set; }
public string NarrativeHTML { get; set; }
}
then refactor the method to depend on that type via generics
private void BuildBulletedList<T>(IEnumerable<T> items) where T : IRender {
List<Run> labels = new List<Run>();
foreach (T item in items) {
if (!string.IsNullOrEmpty(item.NarrativeHTML)) {
var htmlRuns = DocumentHtmlConverter
.Parse(item.NarrativeHTML)
.First()
.ChildElements
.Where(c => c is Run)
.Cast<Run>()
.Select(n => n.CloneNode(true));
labels.Add(new Run(htmlRuns));
} else if (!string.IsNullOrEmpty(item.Name)) {
labels.Add(new Run(new Text(item.Name)));
}
}
BuildList(labels);
}
Now to make a single call, concatenate the lists and then check to see if a bullet list can be built.
var source = hydronicSystem.Equipment.Source.Cast<IRender>();
var distribution = hydronicSystem.Equipment.Distribution.Cast<IRender>();
var terminals = hydronicSystem.Equipment.Terminals.Cast<IRender>();
var bullets = source.Concat(distribution).Concat(terminals);
if (bullets.Any()) {
BuildBulletedList(bullets);
}
I need to Access available Hotel Object From query2, here I am able to access HotelCode value using y.key, but How Can I Access the availableHotel Object from query2.
My Matrix MOdel
public class JsonMatrixModel
{
public class Result
{
public string responseId { get; set; }
public string searchId { get; set; }
public int totalFound { get; set; }
public List<availableHotels> availableHotels { get; set; }
}
public class availableHotels
{
public string processId { get; set; }
public string hotelCode { get; set; }
public string availabilityStatus { get; set; }
public double totalPrice { get; set; }
public double totalTax { get; set; }
public double totalSalePrice { get; set; }
public string currency { get; set; }
public string boardType { get; set; }
public List<rooms> rooms { get; set; }
}
public class rooms
{
public string roomCategory { get; set; }
public List<paxes> paxes { get; set; }
public double totalRoomRate { get; set; }
public List<ratesPerNight> ratesPerNight { get; set; }
}
public class paxes
{
public string paxType { get; set; }
public int age { get; set; }
}
public class ratesPerNight
{
public string date { get; set; }
public double amount { get; set; }
}
}
My Query
Enumerable<IGrouping<string, JsonMatrixModel.availableHotels>> quer2 =
from ff in ddd
from ss in ff.availableHotels.OrderBy(x =>x.totalSalePrice) group ss by ss.hotelCode;
Accessing the Value
foreach (var y in quer2)
{
string ss = y.Key;
}
After you make the grouping, make a projection to a new anonymous object with a property that will have the value of your key, and another could the the list of grouped values for that key.
var quer2 =
from ff in ddd
from ss in ff.availableHotels.OrderBy(x =>x.totalSalePrice)
group ss by ss.hotelCode
select new
{
GroupKey = ss.Key,
GroupValuesList = ss.ToList()
};
Console.WriteLine(quer2.First().GroupKey);
IGroupping is just an IEnumerable with an additional Key property. is this what you want?
var groups = items.GroupBy(p => p.Property);
foreach (var group in groups)
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
Console.WriteLine("\t{0}", item.AnotherProperty);
}
}
I'm trying to build a filtering system. Say you have these models.
public class FilterVM
{
public string ContentRating { get; set; }
public List<FilterChars> FilterChars { get; set; }
public List<FilterCats> FilterCats { get; set; }
public List<FilterTags> FilterTags { get; set; }
}
public class FilterChars
{
public int CharID { get; set; }
public int CharVal { get; set; }
}
public class Book
{
public int BookID { get; set; }
public ICollection<BookCharacteristic> BookCharacteristic { get; set; }
}
public class BookCharacteristic
{
public int ID { get; set; }
public int BookID { get; set; }
public int CharacteristicID { get; set; }
public Book Book { get; set; }
public int Value { get; set; }
public Characteristic Characteristic { get; set; }
}
So a form gets posted and there's a FilterVM with a list of FilterChars now I need to find the books that have the characteristic (CharID) and have a value greater than the submitted value.
This is what I am trying but I can't figure out the right way to write the query.
List<FilterChars> fc = new List<FilterChars>();
foreach (var filter in f.FilterChars.Where(x => x.CharVal > 0)) {
fc.Add(filter);
}
var books = db.Books
.Where(t => fc.Select(y => y.CharID)
.Contains(t.BookCharacteristic
.Any(u => u.CharacteristicID)
)
&& //if there's a match, use the matched BookCharacteristic and Value??
//not sure how to do that
);
public class BookCharacteristicEqualityComparer : IEqualityComparer<BookCharacteristic>
{
public bool Equals(BookCharacteristic x, BookCharacteristic y)
{
return x.CharacteristicID == y.CharacteristicID && x.Value == y.Value;
}
public int GetHashCode(BookCharacteristic obj)
{
return obj.CharacteristicID * obj.Value;
}
}
That's for comparing BookCharacteristics with id and value
var books = db.Books
.Where((book) =>
{
foreach (var filterChar in fc)
{
if (!book.BookCharacteristic.Contains(new BookCharacteristic() {CharacteristicID = filterChar.CharID, Value = filterChar.CharVal},
new BookCharacteristicEqualityComparer()))
return false;
}
return true;
});
find all books that contains all characteristics and values from the filter
hope that helped :)
Edit:
Here is my code, compiles and runs fine (i have no results because i have no data, but no errors )
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var fc = new List<FilterChars>();
var dbBooks = new List<Book>();
var books = dbBooks
.Where((book) =>
{
foreach (var filterChar in fc)
{
if (!book.BookCharacteristic.Contains(new BookCharacteristic() { CharacteristicID = filterChar.CharID, Value = filterChar.CharVal },
new BookCharacteristicEqualityComparer()))
return false;
}
return true;
});
}
}
public class FilterVM
{
public string ContentRating { get; set; }
public List<FilterChars> FilterChars { get; set; }
}
public class FilterChars
{
public int CharID { get; set; }
public int CharVal { get; set; }
}
public class Book
{
public int BookID { get; set; }
public ICollection<BookCharacteristic> BookCharacteristic { get; set; }
}
public class BookCharacteristic
{
public int ID { get; set; }
public int BookID { get; set; }
public int CharacteristicID { get; set; }
public Book Book { get; set; }
public int Value { get; set; }
}
public class BookCharacteristicEqualityComparer : IEqualityComparer<BookCharacteristic>
{
public bool Equals(BookCharacteristic x, BookCharacteristic y)
{
return x.CharacteristicID == y.CharacteristicID && x.Value == y.Value;
}
public int GetHashCode(BookCharacteristic obj)
{
return obj.CharacteristicID * obj.Value;
}
}
I want to use LINQ to pass data from one custom collection to another. Its complicated because the collection has 2 sub collections.
Want to copy data to:
public class Quote
{
public int Id { get; set; }
public string Type { get; set; }
public virtual ICollection<Rate> Rates { get; set; }
}
public class Rate
{
public int Id { get; set; }
public virtual ICollection<Option> Options { get; set; }
}
public class Option
{
public int Id { get; set; }
public decimal Price { get; set; }
}
from:
public class Quote
{
public int QuoteId { get; set; }
public string Type { get; set; }
public string Destination { get; set; }
public List<RateSet> RateSets { get; set; }
}
public class RateSet
{
public int Id { get; set; }
public decimal ValueMin { get; set; }
public decimal ValueMax { get; set; }
public List<Option> Options { get; set; }
}
public class Option
{
public int Id { get; set; }
public string Name { get; set; }
public decimal? Price { get; set; }
}
I was getting somewhere with this but keeping hitting problems...
newQuotes = Quotes
.Select(x => new Quote() {
Id = x.QuoteId,
Rates = x.RateSets.Select( y => new Rate() {
Id = y.Id,
Options = y.Options.Select(z => new Option() {
Id = z.Id,
Price = z.Price
}).ToList(),....
to
Compiled without any errors
// to
public class Quote2
{
public int Id { get; set; }
public string Type { get; set; }
public virtual ICollection<Rate> Rates { get; set; }
}
public class Rate
{
public int Id { get; set; }
public virtual ICollection<Option2> Options { get; set; }
}
public class Option2
{
public int Id { get; set; }
public decimal Price { get; set; }
}
// from
public class Quote1
{
public int QuoteId { get; set; }
public string Type { get; set; }
public string Destination { get; set; }
public List<RateSet> RateSets { get; set; }
}
public class RateSet
{
public int Id { get; set; }
public decimal ValueMin { get; set; }
public decimal ValueMax { get; set; }
public List<Option1> Options { get; set; }
}
public class Option1
{
public int Id { get; set; }
public string Name { get; set; }
public decimal? Price { get; set; }
}
void Main()
{
var Quotes = new List<Quote1>();
var newQuotes = Quotes
.Select(x => new Quote2 {
Id = x.QuoteId,
Rates = x.RateSets == null ? null : x.RateSets.Select( y => new Rate {
Id = y.Id,
Options = y.Options == null ? null : y.Options.Select(z => new Option2 {
Id = z.Id,
Price = z.Price.Value
}).ToList()}).ToList()}).ToList();
}
I would make it a bit more modular:
newQuotes = Quotes.Select(x => new Quote
{
ID = x.QuoteID,
Type = x.Type,
Rates = ConvertRates(x.RateSets)
});
ConvertRates would use the same approach to create its sub objects and could either be a method or a Func:
ICollection<Rate> ConvertRates(IEnumerable<RateSet> oldRates)
{
return oldRates.Select(x => new Rate
{
ID = x.ID,
Options = ConvertOptions(x.Options)
}).ToList();
}
Basically, this is the same approach you used, just split up and readable.
I think what you need to do is define casting between each two corresponding classes, then cast one list into the other.
A simpler way may be to create methods in each class that would convert itself to the other type. Or if you don't want that kind of coupling, create a factory class that will do the conversion for you, one item at a time. Then use link to loop through and convert each item.
Like so:
public class Quote
{
public int Id { get; set; }
public string Type { get; set; }
public virtual ICollection<Rate> Rates { get; set; }
public static Quote FromData(Data.Quote input){
if (input == null) return null;
Quote output = new Quote()
{
Id = input.QuoteId,
Type = input.Type
};
output.Rates = (from i in input.RateSets
select Rate.FromData(i)).ToList();
}
}
public class Rate
{
public int Id { get; set; }
public virtual ICollection<Option> Options { get; set; }
public static Rate FromData(Data.RateSet input)
{
if (input == null) return null;
Rate output = new Rate()
{
Id = input.Id
};
output.Options = (from i in input.Options
select Option.FromData(i)).ToList();
return output;
}
}
public class Option
{
public int Id { get; set; }
public decimal Price { get; set; }
public static Option FromData(Data.Option input)
{
if (input == null) return null;
Option output = new Option()
{
Id = input.Id,
Price = input.Price ?? 0m
};
return output;
}
}
namespace Data {
public class Quote
{
public int QuoteId { get; set; }
public string Type { get; set; }
public string Destination { get; set; }
public List<RateSet> RateSets { get; set; }
}
public class RateSet
{
public int Id { get; set; }
public decimal ValueMin { get; set; }
public decimal ValueMax { get; set; }
public List<Option> Options { get; set; }
}
public class Option
{
public int Id { get; set; }
public string Name { get; set; }
public decimal? Price { get; set; }
}
}
The source class:
public class Post
{
public long ID { get; set; }
[Column(TypeName="nvarchar")]
[Required]
[StringLength(250)]
public string Name { get; set; }
[Column(TypeName="varchar")]
[StringLength(250)]
public string UrlName { get; set; }
[Column(TypeName="ntext")]
public string Excerpt { get; set; }
[Column(TypeName="ntext")]
[Required]
public string Content { get; set; }
public DateTime PostedTime { get; set; }
public DateTime? PublishedTime { get; set; }
public DateTime? LastUpdatedTime { get; set; }
public bool IsPublished { get; set; }
public virtual List<Category> Categories { get; set; }
public virtual List<Comment> Comments { get; set; }
public virtual List<Tag> Tags { get; set; }
}
the destination class
public class Post : Model
{
public long ID { get; set; }
public string Name { get; set; }
public string UrlName { get; set; }
public string Excerpt { get; set; }
public string Content { get; set; }
public DateTime PostedTime { get; set; }
public DateTime LastCommentedTime { get; set; }
public bool IsPublished { get; set; }
public List<Category> Category { get; set; }
public List<Comment> Comments { get; set; }
public List<Tag> Tags { get; set; }
}
I try using EmitMapper to map from each other; when mapping from source to desction, here is the code sampleļ¼
[TestMethod]
public void ShouleMapEntityToModel()
{
Post eP = new Post();
eP.ID = 2;
eP.Comments = new List<Comment>();
eP.Comments.Add(new Comment()
{
ID = 2,
Author = "derek"
});
var mP = eP.Map<Post, mBlog.Core.Models.Post>();
Assert.IsNotNull(mP);
Assert.AreEqual(1, mP.Comments.Count());
}
and I got an exception,
Test method mBlog.Test.EmitMapperTest.ShouleMapEntityToModel threw exception:
System.Exception: Constructor for types [] not found in System.Collections.Generic.IList`1[[mBlog.Core.Models.Post, mBlog.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
I had the same problem, but I have found the solution. Don't user Lists for your destination object. If you use simple arrays in your mBlog.Core.Models.Post object you should get a nicely filled object. So your destination class should look like:
public class Post : Model
{
public long ID { get; set; }
public string Name { get; set; }
public string UrlName { get; set; }
public string Excerpt { get; set; }
public string Content { get; set; }
public DateTime PostedTime { get; set; }
public DateTime LastCommentedTime { get; set; }
public bool IsPublished { get; set; }
public Category[] Category { get; set; }
public Comment[] Comments { get; set; }
public Tag[] Tags { get; set; }
}
This answer shows how to handle IEnumerable to IEnumerable: EmitMapper and List
I believe that can be applied to this case too. Take a look:
This can be done creating a custom class, implementing the interface "ICustomConverterProvider" and adding a ConvertGeneric to the "DefaultMapConfig".
Looking on the source code of EmitMapper, i found a class named "ArraysConverterProvider", which is the default generic converter from ICollections to Arrays.
Adapting the code from this class to work with IEnumerable
collections:
class GenericIEnumerableConverterProvider : ICustomConverterProvider
{
public CustomConverterDescriptor GetCustomConverterDescr(
Type from,
Type to,
MapConfigBaseImpl mappingConfig)
{
var tFromTypeArgs = DefaultCustomConverterProvider.GetGenericArguments(from);
var tToTypeArgs = DefaultCustomConverterProvider.GetGenericArguments(to);
if (tFromTypeArgs == null || tToTypeArgs == null || tFromTypeArgs.Length != 1 || tToTypeArgs.Length != 1)
{
return null;
}
var tFrom = tFromTypeArgs[0];
var tTo = tToTypeArgs[0];
if (tFrom == tTo && (tFrom.IsValueType || mappingConfig.GetRootMappingOperation(tFrom, tTo).ShallowCopy))
{
return new CustomConverterDescriptor
{
ConversionMethodName = "Convert",
ConverterImplementation = typeof(GenericIEnumerableConverter_OneTypes<>),
ConverterClassTypeArguments = new[] { tFrom }
};
}
return new CustomConverterDescriptor
{
ConversionMethodName = "Convert",
ConverterImplementation = typeof(GenericIEnumerableConverter_DifferentTypes<,>),
ConverterClassTypeArguments = new[] { tFrom, tTo }
};
}
}
class GenericIEnumerableConverter_DifferentTypes<TFrom, TTo> : ICustomConverter
{
private Func<TFrom, TTo> _converter;
public IEnumerable<TTo> Convert(IEnumerable<TFrom> from, object state)
{
if (from == null)
{
return null;
}
TTo[] result = new TTo[from.Count()];
int idx = 0;
foreach (var f in from)
{
result[idx++] = _converter(f);
}
return result;
}
public void Initialize(Type from, Type to, MapConfigBaseImpl mappingConfig)
{
var staticConverters = mappingConfig.GetStaticConvertersManager() ?? StaticConvertersManager.DefaultInstance;
var staticConverterMethod = staticConverters.GetStaticConverter(typeof(TFrom), typeof(TTo));
if (staticConverterMethod != null)
{
_converter = (Func<TFrom, TTo>)Delegate.CreateDelegate(
typeof(Func<TFrom, TTo>),
null,
staticConverterMethod
);
}
else
{
_subMapper = ObjectMapperManager.DefaultInstance.GetMapperImpl(typeof(TFrom), typeof(TTo), mappingConfig);
_converter = ConverterBySubmapper;
}
}
ObjectsMapperBaseImpl _subMapper;
private TTo ConverterBySubmapper(TFrom from)
{
return (TTo)_subMapper.Map(from);
}
}
class GenericIEnumerableConverter_OneTypes<T>
{
public IEnumerable<T> Convert(IEnumerable<T> from, object state)
{
if (from == null)
{
return null;
}
return from;
}
}
This code is just a copy with a minimum of adaptation as possible and
can be applyed to objects with many levels of hierarchy.
You can use the above code with the following command:
new DefaultMapConfig().ConvertGeneric(
typeof(IEnumerable<>),
typeof(IEnumerable<>),
new GenericIEnumerableConverterProvider());
This saved my day and I hope to save yours too! hehehe