I have a method MapResults which returns IEnumerable<T> and I have a list temp. I want to add returnVal and temp lists and return IEnumerable<T>.
public class RetrieverClass<T, TEntity> : IRetriever<T, TEntity>
where T : BaseFileEntity
where TEntity : class, IEntity<int>
{
public async Task<IEnumerable<T>> TestMethod(IEnumerable<Item> items)
{
var returnVal = MapResults(result).ToList();
List<TestEntity> temp = new List<TestEntity>();
foreach (var testNo in testNos)
{
TestEntity test = CreateTestEntity(testNo);
temp.Add(test);
}
returnVal.AddRange(temp);
}
private IEnumerable<T> MapResults(IEnumerable<TEntity> results)
{
return results.Select(x => _repository.ObjectMapper.Map<T>(x));
}
}
public class TestEntity : BaseFileEntity
{
}
But its giving error on line returnVal.AddRange(temp).
cannot convert from System.Collections.Generic.List<TestEntity> to
System.Collections.Generic.IEnumerable<T>
As suggested by #Camilo Terevinto and #mjwills return (IEnumerable<T>)retVal; had given me a hint to proceed to solve my issue. I'm posting my answer so that it can help others. Thanks everyone for your help, your comments really helped.
public async Task<IEnumerable<T>> TestMethod(IEnumerable<MasterDataFileOperationItem> items)
{
var ids = items.Select(i => i.Id).ToArray().Select(x => x.ToString()).ToArray();
var result = await _repository.GetAll().Where(x => ids.Contains(x.Id)).ToListAsync();
var returnVal = MapResults(result).ToList();
var temp = CreateTestEntity(testNos);
returnVal.AddRange(temp);
return returnVal;
}
public IEnumerable<T> CreateTestEntity(string[] testNos)
{
List<TestEntity> ls = new List<TestEntity>();
foreach (var testNo in testNos)
{
var TestEntity = new TestEntity
{
TestNo = testNo,
};
ls.Add(TestEntity);
}
return (IEnumerable<T>) ls;
}
Related
I have a code like this:
using System;
using System.Collections.Generic;
using System.Linq;
public interface IMyString
{
string Id {get;set;}
};
public class MyString : IMyString
{
public string Id {get;set;}
}
public static class Extensions
{
public static IEnumerable<IMyString> WithId(this IEnumerable<IMyString> source, string id)
{
return source.Where(x => x.Id == id);
}
}
public class Program
{
private static List<T> GetMyStrings<T>(string key, List<T> input)
where T: IMyString
{
return input.WithId(key).ToList();
}
public static void Main()
{
var foo = new List<MyString>{ new MyString { Id = "yes"}, new MyString { Id = "no" } };
var result = GetMyStrings("yes", foo);
var result2 = foo.WithId("no");
Console.WriteLine(result2);
}
}
Why does input.WithId(key).ToList() cause a syntax error, while foo.WithId("no") is OK? Is there a way to make the method GetMyStrings work?
Without the context of your code it is a little difficult to help too much, but your type constraints for the two methods are different. You have two options:
Option 1:
public static class Extensions
{
public static IEnumerable<T> WithId<T>(this IEnumerable<T> source, string id) where T: IMyString
{
return source.Where(x => x.Id == id);
}
}
Option 2:
private static List<IMyString> GetMyStrings(string key, List<IMyString> input)
{
return input.WithId(key).ToList();
}
public static void Main()
{
var foo = new List<IMyString>{ new MyString { Id = "yes"}, new MyString { Id = "no" } };
var result = GetMyStrings("yes", foo);
var result2 = foo.WithId("no");
Console.WriteLine(result2);
}
Here is a dotnetfiddle with the second option as a working piece of code:
public static IEnumerable<T> WithId<T>(this IEnumerable<T> source, string id)
where T : IMyString
{
return source.Where(x => x.Id == id);
}
So when you get back an list, one value is filled by the repository but the other you want to have the same value for each item in the list. It feels like an for each loop is the a lot of code for simple functionality. Is there a way to shorten the code.
So some context. This is an example class.
public class ExampleClass
{
public string A { get; set; }
public string B { get; set;
}
This is an method that works:
public IEnumerable<ExampleClass> GetAll(string bValue)
{
var exampleList = repo.GetAll(); //Asume that the repo gives back the an list with A filled;
var returnValue = new List<ExampleClass>();
foreach (var item in exampleList)
{
item.B= bValue;
returnValue.Add(item);
}
return returnValue;
}
It would be great if there could something like:
public IEnumerable<ExampleClass> GetAll(string bValue)
{
return repo.GetAll().Map(i => i.B = bValue);
}
Does anyone knows something like this.
You could use yield return:
public IEnumerable<ExampleClass> GetAll(string bValue)
{
foreach (var item in repo.GetAll())
{
item.B = bValue;
yield return item;
}
}
You can also turn this into an extension method for more fluency:
public static class IEnumerableExtensions
{
public static IEnumerable<T> Map<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var item in source)
{
action(item);
yield return item;
}
}
}
// usage
public IEnumerable<ExampleClass> GetAll(string bValue)
{
return repo.GetAll().Map(x => x.B = bValue);
}
You can try LINQ. According to this link:
Update all objects in a collection using LINQ , you can do this:
repo.getAll().Select(c => {c.B = value; return c;}).ToList();
However, according to Jon Skeet, it's better to just use Foreach loop.
https://stackoverflow.com/a/7851940/5779825
return repo.GetAll().ToList().ForEach(i => i.B = bValue);
This should work. Not tested though.
I think you can use this approach:
return exampleList.Select(i => { i.B = bValue; return i; });
Here is pseudo code for a basic example:
// Cannot touch
public class QAS
{
public IEnumerable<T> Execute<T>(IEnumerable<Point> i) where T : class, IPointResults, new()
{
//returns object using IPointResults
}
public IEnumerable<T> Execute<T>(IEnumerable<Seg> i) where T : class, ISegResults, new()
{
//returns object using ISegResults
}
}
public interface IPointResults
{
int turtle;
}
public interface ISegResult
{
double bird;
}
public interface PointSeg
{
string id;
}
public class Point : PointSeg
{
string id;
int x;
int y;
}
public class Seg : PointSeg
{
string id;
string q;
}
I have these two methods which are very similar, I'd like to utilize there generic where clauses by take the similar code and combine it to one:
public IEnumerable<T> GetAttributes<T>(IEnumerable<Point> pts) where T : class, IPointResults, new()
{
var queryAttributeSet = new QAS();
var rv = new List<T>();
var batches = pts.Batch(25);
Log.Debug($"Attempting to get {total} records using {batches.Count()} requests");
foreach (var batch in batches)
{
var results = queryAttributeSet.Execute<T>(batch);
rv.AddRange(results);
}
return rv;
}
public IEnumerable<T> GetAttributes<T>(IEnumerable<Seg> segments) where T : class, ISegResults, new()
{
var queryAttributeSet = new QAS();
var rv = new List<T>();
var batches = segments.Batch(25);
Log.Debug($"Attempting to get {total} records using {batches.Count()} requests");
foreach (var batch in batches)
{
var results = queryAttributeSet.Execute<T>(batch);
rv.AddRange(results);
}
return rv;
}
My attempt:
public IEnumerable<T> GetAttributes<T>(IEnumerable<Point> pts) where T : class, IPointResults, new()
{
return GetAttributesHelper<T>(pts);
}
public IEnumerable<T> GetAttributes<T>(IEnumerable<Seg> segments) where T : class, ISegResults, new()
{
return GetAttributesHelper<T>(segments);
}
public IEnumerable<T> GetAttributesHelper<T>(IEnumerable<PointSeg> x) where T : class, new()
{
var queryAttributeSet = new QAS();
var rv = new List<T>();
var batches = x.Batch(25);
Log.Debug($"Attempting to get {total} records using {batches.Count()} requests");
foreach (var batch in batches)
{
var results = queryAttributeSet.Execute<T>(batch);
rv.AddRange(results);
}
return rv;
}
I try to utilize that Point and Seg follow the interface IPointSeg but unfortunately this doesn't work because QAS.Execute doesn't know how to take in IPointSeg and it cannot be modified.
Then I thought maybe if I somehow was able to tell it which function to use by delegates:
public IEnumerable<T> GetAttributes<T>(IEnumerable<Point> pts) where T : class, IPointResults, new()
{
var queryAttributeSet = new QAS();
Func<IEnumerable<Point>, T> execute = queryAttributeSet.Execute<T>;
return GetAttributesHelper<T>(pts, execute);
}
public IEnumerable<T> GetAttributes<T>(IEnumerable<Seg> segments) where T : class, ISegResults, new()
{
var queryAttributeSet = new QAS();
Func<IEnumerable<Seg>, T> execute = queryAttributeSet.Execute<T>;
return GetAttributesHelper<T>(segments, execute);
}
public IEnumerable<T> GetAttributesHelper<T>(IEnumerable<PointSeg> x, Func<IEnumerable<PointSeg>, T> execute) where T : class, new()
{
var rv = new List<T>();
var batches = x.Batch(25);
Log.Debug($"Attempting to get {total} records using {batches.Count()} requests");
foreach (var batch in batches)
{
var results = execute(batch);
rv.AddRange(results);
}
return rv;
}
This doesnt work because you cant use an interface in Func<> to as a way to send 2 types of Func<>s to a function.
I just want to use QAS.Execute while wrapping the functionality with the batching logic I written and not have it duplicated
I don't know who resolve this segment code with variance:
I have an abstract father class:
public abstract class PdfObject
{...}
And two child classes:
public class PdfText : PdfObject
{...}
public class PdfImage : PdfObject
{...}
Now, my wrong or empiric code is the next:
public IList<PdfText> GetTexts()
{
List<PdfText> result = new List<PdfText>();
List<PdfObject> list = GetList();
foreach(var item in list)
{
if(item is PdfText) result.Add(item)
}
return result;
}
public List<PdfObject> GetList()
{...}
Well, i read a lot of this theme, but don't stand how use variance in generics or use a better solution for this issue.
Please, help me and thanks.
This doesn't have much to do with variance, directly. Your problem is here:
public IList<PdfText> GetTexts()
{
List<PdfText> result = new List<PdfText>();
List<PdfObject> list = GetList();
foreach(var item in list)
{
if(item is PdfText) result.Add(item)
}
return result;
}
The static type of the item variable is PdfObject so you cannot add it to result; you need to cast it. For example
if (item is PdfText) result.Add((PdfText)item);
This is inefficient because you check the type twice: once for the is operator and once for the cast. Instead, you're supposed to do this:
public IList<PdfText> GetTexts()
{
List<PdfText> result = new List<PdfText>();
List<PdfObject> list = GetList();
foreach(var item in list)
{
var textItem = item as PdfText
if (textItem != null) result.Add(textItem)
}
return result;
}
Or, you can use linq:
var result = GetList().OfType<PdfText>().ToList();
You could do this...
public IList<PdfText> GetTexts()
{
List<PdfText> result = GetList()
.Where(x => x is PdfText)
.Select(x => (PdfText)x)
.ToList();
return result;
}
Edited: This works, but OfType is better.
You could have a better solution in this situation.
public class ClientOfPdfObject<T> where T: PdfObject
{
public List<T> GetItems()
{
List<PdfObject> list = GetList();
var result = new List<T>();
foreach (var pdfObject in list)
{
if (typeof (T) == pdfObject.GetType())
result.Add((T) pdfObject);
}
return result;
}
//Get PdfObjects somewhere (ex. Db)
private List<PdfObject> GetList()
{
var list = new List<PdfObject>
{
new PdfImage(),
new PdfImage(),
new PdfImage(),
new PdfText(),
new PdfText(),
new PdfText(),
new PdfText()
};
return list;
}
}
static void main()
{
var text = new ClientOfPdfObject<PdfText>();
//contains 4 itmes (PdfText)
var pdfTexts = text.GetItems();
var image = new ClientOfPdfObject<PdfImage>();
//contains 3 items (PdfImage)
var pdfImages = image.GetItems();
}
Tomorrow, when you add more pdf objects (ex. PdfGraph), you don't need to change anything.
I am trying to apply the new mocking of EF6 to my existing code.
I have a class that Extends DbSet. One of the methods call the base class (BdSet) Create method. Here is the a sample code (not the complete solution or real names):
public class DerivedDbSet<TEntity> : DbSet<TEntity>, IKeyValueDbSet<TEntity>, IOrderedQueryable<TEntity> where TEntity : class
{
public virtual bool Add(string value1, string value2) {
var entity = Create(); // There is no direct implementation of the Create method it is calling the base method
// Do something with the values
this.Add(entity);
return true;
}
}
I am mocking using the Test Doubles sample (here is the peace of code):
var data = new List<DummyEntity> {
new DummyEntity { Value1 = "First", Value2 = "001" },
new DummyEntity { Value1 = "Second", Value2 = "002" }
}.AsQueryable();
var mock = new Mock<DerivedDbSet<DummyEntity>>();
mock.CallBase = true;
mock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(source.Provider);
mock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(source.Expression);
mock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(source.ElementType);
mock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(source.GetEnumerator());
I've set the CallBase property to true to try to force the call to the base class...
But I keep receiving the following error:
System.NotImplementedException: The member 'Create' has not been implemented on type 'DerivedDbSet1Proxy' which inherits from 'DbSet1'. Test doubles for 'DbSet`1' must provide implementations of methods and properties that are used.
I want the call of create to fallback to the default implementation in DbSet.
Can someone help me with that?
After some struggle with the internal functions and async references of mocking a DbSet I came out with a helper class that solved most of my problems and might serve as base to someone implementation.
Here is the code:
public static class MockHelper
{
internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider {
private readonly IQueryProvider _inner;
internal TestDbAsyncQueryProvider(IQueryProvider inner) { _inner = inner; }
public IQueryable CreateQuery(Expression expression) { return new TestDbAsyncEnumerable<TEntity>(expression); }
public IQueryable<TElement> CreateQuery<TElement>(Expression expression) { return new TestDbAsyncEnumerable<TElement>(expression); }
public object Execute(Expression expression) { return _inner.Execute(expression); }
public TResult Execute<TResult>(Expression expression) { return _inner.Execute<TResult>(expression); }
public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken) { return Task.FromResult(Execute(expression)); }
public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken) { return Task.FromResult(Execute<TResult>(expression)); }
}
internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T> {
public TestDbAsyncEnumerable(IEnumerable<T> enumerable) : base(enumerable) { }
public TestDbAsyncEnumerable(Expression expression) : base(expression) { }
public IDbAsyncEnumerator<T> GetAsyncEnumerator() { return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator()); }
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() { return GetAsyncEnumerator(); }
public IQueryProvider Provider { get { return new TestDbAsyncQueryProvider<T>(this); } }
}
internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> {
private readonly IEnumerator<T> _inner;
public TestDbAsyncEnumerator(IEnumerator<T> inner) { _inner = inner; }
public void Dispose() { _inner.Dispose(); }
public Task<bool> MoveNextAsync(CancellationToken cancellationToken) { return Task.FromResult(_inner.MoveNext()); }
public T Current { get { return _inner.Current; } }
object IDbAsyncEnumerator.Current { get { return Current; } }
}
public static Mock<TDbSet> CreateDbSet<TDbSet, TEntity>(IList<TEntity> data, Func<object[], TEntity> find = null)
where TDbSet : class, IDbSet<TEntity>
where TEntity : class, new() {
var source = data.AsQueryable();
var mock = new Mock<TDbSet> { CallBase = true };
mock.As<IQueryable<TEntity>>().Setup(m => m.Expression).Returns(source.Expression);
mock.As<IQueryable<TEntity>>().Setup(m => m.ElementType).Returns(source.ElementType);
mock.As<IQueryable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(source.GetEnumerator());
mock.As<IQueryable<TEntity>>().Setup(m => m.Provider).Returns(new TestDbAsyncQueryProvider<TEntity>(source.Provider));
mock.As<IDbAsyncEnumerable<TEntity>>().Setup(m => m.GetAsyncEnumerator()).Returns(new TestDbAsyncEnumerator<TEntity>(data.GetEnumerator()));
mock.As<IDbSet<TEntity>>().Setup(m => m.Create()).Returns(new TEntity());
mock.As<IDbSet<TEntity>>().Setup(m => m.Add(It.IsAny<TEntity>())).Returns<TEntity>(i => { data.Add(i); return i; });
mock.As<IDbSet<TEntity>>().Setup(m => m.Remove(It.IsAny<TEntity>())).Returns<TEntity>(i => { data.Remove(i); return i; });
if (find != null) mock.As<IDbSet<TEntity>>().Setup(m => m.Find(It.IsAny<object[]>())).Returns(find);
return mock;
}
public static Mock<DbSet<TEntity>> CreateDbSet<TEntity>(IList<TEntity> data, Func<object[], TEntity> find = null)
where TEntity : class, new() {
return CreateDbSet<DbSet<TEntity>, TEntity>(data, find);
}
}
And here is a use sample (based on the names I've given before):
var data = new List<DummyEntity> {
new DummyEntity { Value1 = "First", Value2 = "001" } },
new DummyEntity { Value1 = "Second", Value2 = "002" } }
};
var mockDummyEntities = MockHelper.CreateDbSet<DerivedDbSet<DummyEntities>, DummyEntities>(data, i => data.FirstOrDefault(k => k.Value2 == (string)i[0]));
var mockContext = new Mock<DummyDbContext>();
mockContext.Setup(c => c.DummyEntities).Returns(mockDummyEntities.Object);
Any suggestions on how to improve this solution is very welcome.
Regards
This is a modified version based on Andre that worked for me. Note, that I did not need the async references. Code will add all derived classes (if any)
Usage:
/// <summary>
///
/// </summary>
[TestMethod]
public void SomeTest()
{
//Setup
var mockContext = new Mock<FakeDbContext>();
//SomeClass can be abstract or concrete
mockContext.createFakeDBSet<SomeClass>();
var db = mockContext.Object;
//Setup create(s) if needed on concrete classes
//Mock.Get(db.Set<SomeOtherClass>()).Setup(x => x.Create()).Returns(new SomeOtherClass());
//DO Stuff
var list1 = db.Set<SomeClass>().ToList();
//SomeOtherClass derived from SomeClass
var subList1 = db.Set<SomeOtherClass>().ToList();
CollectionAssert.AreEquivalent(list1.OfType<SomeOtherClass>.ToList(), subList1);
}
Code:
/// <summary>
/// http://stackoverflow.com/questions/21943328/ef6-mocking-derived-dbsets
/// </summary>
public static class MoqSetupExtensions
{
static IEnumerable<Type> domainTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes());
public static Mock<DbSet<T>> createFakeDBSet<T>(this Mock<FakeDbContext> db, List<T> list = null, Func<List<T>, object[], T> find = null, bool createDerivedSets = true) where T : class
{
list = list ?? new List<T>();
var data = list.AsQueryable();
//var mockSet = MockHelper.CreateDbSet(list, find);
var mockSet = new Mock<DbSet<T>>() { CallBase = true };
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(() => { return data.Provider; });
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(() => { return data.Expression; });
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(() => { return data.ElementType; });
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => { return list.GetEnumerator(); });
mockSet.Setup(m => m.Add(It.IsAny<T>())).Returns<T>(i => { list.Add(i); return i; });
mockSet.Setup(m => m.AddRange(It.IsAny<IEnumerable<T>>())).Returns<IEnumerable<T>>((i) => { list.AddRange(i); return i; });
mockSet.Setup(m => m.Remove(It.IsAny<T>())).Returns<T>(i => { list.Remove(i); return i; });
if (find != null) mockSet.As<IDbSet<T>>().Setup(m => m.Find(It.IsAny<object[]>())).Returns<object[]>((i) => { return find(list, i); });
//mockSet.Setup(m => m.Create()).Returns(new T());
db.Setup(x => x.Set<T>()).Returns(mockSet.Object);
//Setup all derived classes
if (createDerivedSets)
{
var type = typeof(T);
var concreteTypes = domainTypes.Where(x => type.IsAssignableFrom(x) && type != x).ToList();
var method = typeof(MoqSetupExtensions).GetMethod("createFakeDBSetSubType");
foreach (var item in concreteTypes)
{
var invokeResult = method.MakeGenericMethod(type, item)
.Invoke(null, new object[] { db, mockSet });
}
}
return mockSet;
}
public static Mock<DbSet<SubType>> createFakeDBSetSubType<BaseType, SubType>(this Mock<FakeDbContext> db, Mock<DbSet<BaseType>> baseSet)
where BaseType : class
where SubType : class, BaseType
{
var dbSet = db.Object.Set<BaseType>();
var mockSet = new Mock<DbSet<SubType>>() { CallBase = true };
mockSet.As<IQueryable<SubType>>().Setup(m => m.Provider).Returns(() => { return dbSet.OfType<SubType>().Provider; });
mockSet.As<IQueryable<SubType>>().Setup(m => m.Expression).Returns(() => { return dbSet.OfType<SubType>().Expression; });
mockSet.As<IQueryable<SubType>>().Setup(m => m.ElementType).Returns(() => { return dbSet.OfType<SubType>().ElementType; });
mockSet.As<IQueryable<SubType>>().Setup(m => m.GetEnumerator()).Returns(() => { return dbSet.OfType<SubType>().GetEnumerator(); });
mockSet.Setup(m => m.Add(It.IsAny<SubType>())).Returns<SubType>(i => { dbSet.Add(i); return i; });
mockSet.Setup(m => m.AddRange(It.IsAny<IEnumerable<SubType>>())).Returns<IEnumerable<SubType>>((i) => { dbSet.AddRange(i); return i; });
mockSet.Setup(m => m.Remove(It.IsAny<SubType>())).Returns<SubType>(i => { dbSet.Remove(i); return i; });
mockSet.As<IDbSet<SubType>>().Setup(m => m.Find(It.IsAny<object[]>())).Returns<object[]>((i) => { return dbSet.Find(i) as SubType; });
baseSet.Setup(m => m.Create<SubType>()).Returns(() => { return mockSet.Object.Create(); });
db.Setup(x => x.Set<SubType>()).Returns(mockSet.Object);
return mockSet;
}
}
Microsoft published a very well explained guide providing an in-memory implementation of DbSet which has a complete implemention for all the methods on DbSet.
Check the article at http://msdn.microsoft.com/en-us/data/dn314431.aspx#doubles