Protobuf-net - list of objects with parent reference - list

I have a simple class with reference to parent object. All objects are in one list (even parent objects). Is it possible to keep references references after deserialization?
In my code I have something like this:
[ProtoContract]
public class ProtoItem
{
[ProtoMember(1)]
public int Value { get; set; }
[ProtoMember(2, AsReference = true)]
public ProtoItem BaseItem { get; set; }
}
And main looks like that:
static void Main()
{
var itemParent = new ProtoItem { Value = 1 };
var item2 = new ProtoItem { Value = 2, BaseItem = itemParent };
var item3 = new ProtoItem { Value = 3, BaseItem = itemParent };
var parentListToWrite = new List<ProtoItem> {itemParent, item2, item3};
const string file = "protofile.txt";
try { File.Delete(file); }
catch { };
using (var fs = File.OpenWrite(file)) { Serializer.Serialize(fs,
parentListToWrite); }
List<ProtoItem> readList;
using (var fs = File.OpenRead(file)) { readList =
Serializer.Deserialize<List<ProtoItem>>(fs); }
if (readList[0] == readList[2].BaseItem)
{
//how to make it equal?
}
if (readList[0] == readList[1].BaseItem)
{
//how to make it equal?
}
}
Is it possible to deserialize that if conditions works?

The protobuf specification doesn't have the notion of object identity. protobuf-net does (as an optionally enabled feature), but it doesn't currently work for list items directly, although I suspect it probably should. Since it would break the format, though, it would need explicit enabling if I fixed this.
But the following code works today - note that what I have done here is to wrap the top-level list items in a wrapper that just encapsulates the ProtoItem, but in doing so enables reference-tracking. Not ideal, but: it works.
using ProtoBuf;
using System.Collections.Generic;
using System.IO;
[ProtoContract(AsReferenceDefault=true)]
public class ProtoItem
{
[ProtoMember(1)]
public int Value { get; set; }
[ProtoMember(2)]
public ProtoItem BaseItem { get; set; }
}
[ProtoContract]
public class Wrapper
{
[ProtoMember(1, DataFormat = DataFormat.Group)]
public ProtoItem Item { get;set; }
public static implicit operator ProtoItem(Wrapper value)
{
return value == null ? null : value.Item;
}
public static implicit operator Wrapper(ProtoItem value)
{
return value == null ? null : new Wrapper { Item = value };
}
}
static class Program
{
static void Main()
{
var itemParent = new ProtoItem { Value = 1 };
var item2 = new ProtoItem { Value = 2, BaseItem = itemParent };
var item3 = new ProtoItem { Value = 3, BaseItem = itemParent };
var parentListToWrite = new List<Wrapper> { itemParent, item2, item3 };
const string file = "protofile.txt";
try
{ File.Delete(file); }
catch
{ };
using (var fs = File.OpenWrite(file))
{
Serializer.Serialize(fs,
parentListToWrite);
}
List<Wrapper> readList;
using (var fs = File.OpenRead(file))
{
readList = Serializer.Deserialize<List<Wrapper>>(fs);
}
if (readList[0].Item == readList[2].Item.BaseItem)
{
//how to make it equal?
System.Console.WriteLine("eq");
}
if (readList[0].Item == readList[1].Item.BaseItem)
{
//how to make it equal?
System.Console.WriteLine("eq");
}
}
}

Related

Mock DBSet<T> and call AsQueryable method return an empty list

I use entity framework core 6, XUnit for testing, Moq 4.16.1
I have a List, Mock it as DBSet<T>, I call AsQueryable method on DBSet<T> then return a empty list. If i mock AsQueryable method on DBSet<T>, i will have a expected list. Can you tell me Why?
This is my code
public static class MockDbExtensions
{
public static Mock<DbSet<T>> MockDbSet<T>(this IQueryable<T> testData) where T : class
{
Mock<DbSet<T>> dbSetMock = new Mock<DbSet<T>>();
dbSetMock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(new TestAsyncQueryProvider<T>(testData.Provider));
dbSetMock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(testData.Expression);
dbSetMock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(testData.ElementType);
dbSetMock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => testData.GetEnumerator());
dbSetMock.As<IAsyncEnumerable<T>>().Setup(m => m.GetAsyncEnumerator(default)).Returns(() => new TestAsyncEnumerator<T>(testData.GetEnumerator()));
return dbSetMock;
}
public static Mock<DbSet<T>> MockDbSet<T>(this IEnumerable<T> elements) where T : class
{
var testData = elements.AsQueryable();
return testData.MockDbSet();
}
public static Mock<DbSet<T>> MockDbSet<T>(this T[] elements) where T : class
{
var testData = elements.AsQueryable();
return testData.MockDbSet();
}
}
internal class TestAsyncQueryProvider<TEntity> : IAsyncQueryProvider
{
private readonly IQueryProvider _inner;
internal TestAsyncQueryProvider(IQueryProvider inner)
{
_inner = inner;
}
public IQueryable CreateQuery(Expression expression)
{
return new TestAsyncEnumerable<TEntity>(expression);
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestAsyncEnumerable<TElement>(expression);
}
public object Execute(Expression expression)
{
return _inner.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
return _inner.Execute<TResult>(expression);
}
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression expression)
{
return new TestAsyncEnumerable<TResult>(expression);
}
public TResult ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken = new CancellationToken())
{
var expectedResultType = typeof(TResult).GetGenericArguments()[0];
var executionResult = ((IQueryProvider)this).Execute(expression);
return (TResult)typeof(Task).GetMethod(nameof(Task.FromResult))
.MakeGenericMethod(expectedResultType)
.Invoke(null, new[] { executionResult });
}
}
internal class TestAsyncEnumerable<T> : EnumerableQuery<T>, IAsyncEnumerable<T>, IQueryable<T>
{
public TestAsyncEnumerable(IEnumerable<T> enumerable)
: base(enumerable)
{ }
public TestAsyncEnumerable(Expression expression)
: base(expression)
{ }
public IAsyncEnumerator<T> GetEnumerator()
{
return new TestAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new TestAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}
IQueryProvider IQueryable.Provider => new TestAsyncQueryProvider<T>(this);
}
internal class TestAsyncEnumerator<T> : IAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;
public TestAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}
public void Dispose()
{
_inner.Dispose();
}
public T Current => _inner.Current;
public Task<bool> MoveNext(CancellationToken cancellationToken)
{
return Task.FromResult(_inner.MoveNext());
}
public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(_inner.MoveNext());
public ValueTask DisposeAsync()
{
_inner.Dispose();
return new ValueTask();
}
}
public class ReportTemplateServiceTests
{
private List<ReportTemplateType> CreateReportTemplateTypes()
{
return new List<ReportTemplateType>
{
new ReportTemplateType { Id = new Guid("144013ED-2D77-4572-8AB4-483C66E4EF1D"), Name = "Financial statements", DisplayOrder = 3, CmsId = 101475, IsActive = true },
new ReportTemplateType { Id = new Guid("058F8F85-A735-48F3-B526-79855FFF1EB0"), Name = "Reports", DisplayOrder = 1, CmsId = 100473, IsActive = true },
new ReportTemplateType { Id = new Guid("69D55B31-69BB-4BBC-82F1-A707B484E99B"), Name = "Letters", DisplayOrder = 2, CmsId = 100474, IsActive = true },
new ReportTemplateType { Id = new Guid("19D2650B-CE8E-4B54-95D9-ACAFA5C1CE40"), Name = "Custom working papers", DisplayOrder = 4, CmsId = 101476, IsActive = true },
};
}
public async void CreateReportTemplateAsync_Success()
{
// Arrange
var reportTemplates = CreateReportTemplates().MockDbSet().Object;
var a = reportTemplates.AsQueryable().ToList(); // return empty list after call AsQueryable()
}
}
I mock AsQueryable method on DBSet<T>, i will have a expected list.

Moq an interface and setting up a mock

I have an Interface to check vowel and to return a char as
public interface IVowChecker
{
bool VowCheck(char a);
char ReturnChar(int n);
Student GetStudentById(int n);
}
It's concrete class implementation
public class VowChecker:IVowChecker
{
public bool VowCheck(char a)
{
if (a == 'a' || a == 'A')
return true;
return false;
}
public char ReturnChar(int n)
{
return (char)n;
}
public Student GetStudentById(int n)
{
var list = new []
{
new Student{RollNo=1,Name="A"},
new Student{RollNo=2,Name="B"},
new Student{RollNo=3,Name="C"},
new Student{RollNo=4,Name="D"},
new Student{RollNo=5,Name="E"},
new Student{RollNo=6,Name="F"},
};
var student = from i in list
where i.RollNo == n
select i;
return student.FirstOrDefault();
}
}
And a service using this VowChecker
public class MyCharService
{
private readonly IVowChecker _checker;
public MyCharService(IVowChecker checker)
{
_checker = checker;
}
public bool CheckInput(char a)
{
return _checker.VowCheck(a);
}
public char ReturnChar(int a)
{
return _checker.ReturnChar(a);
}
public Student GetStudentById(int n)
{
return _checker.GetStudentById(n);
}
}
I am using Xunit testing framework for unit testing and Moq library.
My unit test code is
public class MyCharServiceShould
{
...
[Theory]
[InlineData(65)]
[InlineData(68)]
public void BeAbleToReturnChar(int n)
{
var service = new Mock<IVowChecker>();
service.Setup(i => i.ReturnChar(n)).Returns('A');
var obj = new MyCharService(service.Object);
var result = obj.ReturnChar(n);
}
[Theory]
[InlineData(2)]
public void BeAbleToRetrieveStudent(int n)
{
var service = new Mock<IVowChecker>();
service.Setup<Student>(i => i.GetStudentById(n)).Returns<Student>(f => (Student)f);
var ob = new MyCharService(service.Object);
var res = ob.GetStudentById(2);
Assert.Equal(res.Name, "B");
}
}
My Student class
public class Student
{
public int RollNo{ get; set; }
public string Name { get; set; }
}
I have used a debugger in the last line of my test and checked the values of both the tests. For the 1st test I am expecting 'A' as the result and for the 2nd test I am expecting 'D' as the result. But in both the cases I am getting 'A' as the result. Can anyone kindly help me out where I am missing out the concept. Thank you.
The problem is that the setup for ReturnChar
service.Setup(i => i.ReturnChar(n)).Returns('A');
says,
Whenever ReturnChar() is called, give an answer of 'A'
It ignores the input 'n' and just returns 'A'. If you want it to return a different character for each test you will need to tweak the setup.
Perhaps
mockService.Setup(mk => mk.ReturnChar(It.IsAny<int>())).Returns<int>(n => (char)n);
EDIT: Extension to show returning objects (and fixed syntax on previous answer)
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
public interface IService
{
Student FindStudentById(int id);
}
[TestMethod]
public void FindStudents()
{
var students = new[]
{
new Student {Id = 1, Name = "Mon" },
new Student {Id = 2, Name = "Tue" },
new Student {Id = 3, Name = "Wed" },
new Student {Id = 4, Name = "Thu" },
};
var mockService = new Mock<IService>();
mockService.Setup(mk => mk.FindStudentById(It.IsAny<int>())).Returns<int>(id => students.First(s => s.Id == id));
Assert.AreEqual("Wed", mockService.Object.FindStudentById(3).Name);
}

Dictionary int, myclass

That's my class
public class PersonelAtama
{
public int PersonelID { get; set; }
public int YonetimTalepID { get; set; }
public bool durum { get; set; }
}
I want to doDictionary<int,list<myclass>>
Dictionary<int, List<PersonelAtama>>
PersonelAtamaListesi = new Dictionary<int, List<PersonelAtama>>();
How to insert into the list
PersonelAtamaListesi.Add
How assignments are made
PersonelAtamaListesi[0][1]
PersonelAtamaListesi.Add(0,new PersonelAtama()
{
PersonelID = personelID,
YonetimTalepID = yonetimTalepID,
durum = false
});
assignment into the list and how to use again
I want to add to the list and component values to achieve. I want to sample code.
You have List as TValue so:
PersonelAtamaListesi.Add(0, new List<PersonelAtama>()
{
new PersonelAtama()
{
PersonelID = 1,
YonetimTalepID = 2,
durum = false
},
new PersonelAtama()
{
PersonelID = 11,
YonetimTalepID = 222,
durum = true
}
});

Reading objects from webservice actionscript

I need to read objects and save them in array. I did that on c# but can't figure out how to do that on actionscript.
c# example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestingWSDLLOad.ServiceReference2;
namespace TestingWSDLLOad
{
class Program
{
static void Main(string[] args)
{
ServiceReference2.Service1Client testas = new ServiceReference2.Service1Client();
SortedList<int, PlayListItem> playList = new SortedList<int, PlayListItem>();
int cc = 0;
foreach (var resultas in testas.GetPlayList(394570))
{
PlayListItem ss = new PlayListItem(resultas.Id, resultas.VideoId, resultas.Path);
playList.Add(cc, ss);
cc++;
}
Console.WriteLine(playList[0].Id);
Console.ReadKey();
}
}
public class PlayListItem
{
public int VideoId { get; private set; }
public string Path { get; private set; }
public int Id { get; private set; }
public PlayListItem(int id, int videoId, string path)
{
Id = id;
VideoId = videoId;
Path = path;
}
}
}
I know how to get a simple result from wsdl using actionscript, but don't know how to get objects with parameteres and save them.
Service has a method GetPlaylist(int value) which returns an array of objects (id, videoId, path). How to handle this and save them ?
Here is my as3:
package {
public class data extends CasparTemplate {
var flvControl:FLVPlayback;
var refreshTimer:Timer;
var videoList:Array;
var videoNew:Array;
var videoMaxIds:Array;
var videoNewMaxIds:Array;
var videoIndex:uint;
var videoIdFrom:uint;
var loopAtEnd:Boolean;
var _playListItems:Array;
var _playList:PlayListItem;
var gotNewPlaylist:Boolean;
var webService:WebService;
var serviceOperation:AbstractOperation;
public function data()
{
_playListItems = new Array();
flvControl = new FLVPlayback();
videoNew = new Array();
videoNewMaxIds = new Array();
videoIndex = 0;
videoIdFrom = videoMaxIds[videoIndex];
loopAtEnd = true;
gotNewPlaylist = false;
refreshTimer = new Timer(20000);
refreshTimer.addEventListener(TimerEvent.TIMER, getNewPlaylist);
refreshTimer.start();
flvControl.addEventListener(VideoEvent.COMPLETE, completeHandler);
flvControl.addEventListener(VideoEvent.STATE_CHANGE, vidState);
flvControl.setSize(720, 576);
flvControl.visible = true;
//addChild(flvControl);
var url:String = "http://xxx/yyy.svc?wsdl";
webService = new WebService();
webService.loadWSDL(url);
webService.addEventListener(LoadEvent.LOAD, BuildServiceRequest);
}
function BuildServiceRequest(evt:LoadEvent):void
{
webService.removeEventListener(LoadEvent.LOAD, BuildServiceRequest);
//serviceOperation.addEventListener(ResultEvent.RESULT, displayResult);
for (var resultas in webService.getOperation("GetPlaylist(394575)"))
{
trace(resultas.Id);
}
//serviceOperation = webService.getOperation("GetPlaylist");
//serviceOperation.arguments[{videoId: "394575"}];
}
private function displayResult(e:ResultEvent):void
{
trace("sss");
}
// Handle the video completion (load the next video)
function completeHandler(event:VideoEvent):void
{
if (gotNewPlaylist)
{
videoList = videoNew;
videoMaxIds = videoNewMaxIds;
videoNew = null;
videoNewMaxIds = null;
gotNewPlaylist = false;
videoIndex = 0;
} else
videoIndex++;
nextVideo();
}
private function vidState(e:VideoEvent):void {
var flvPlayer:FLVPlayback = e.currentTarget as FLVPlayback;
if (flvPlayer.state==VideoState.CONNECTION_ERROR) {
trace("FLVPlayer Connection Error! -> path : "+flvPlayer.source);
videoIndex++;
nextVideo();
} else if (flvPlayer.state==VideoState.DISCONNECTED) {
videoIndex++;
nextVideo();
}
}
function nextVideo():void
{
trace("Video List:"+videoList.toString());
if( videoIndex == videoList.length ){
if( loopAtEnd )
{
videoIndex = 0;
} else { return; }
}
flvControl.source = videoList[videoIndex];
if (videoIdFrom < videoMaxIds[videoIndex])
videoIdFrom = videoMaxIds[videoIndex];
trace(videoIdFrom);
}
}
}
internal class PlayListItem
{
private var _videoId:int;
private var _path:String;
private var _id:int;
public function get VideoId():int { return _videoId; }
public function get Path():String { return _path; }
public function get Id():int { return _id; }
public function set VideoId(setValue:int):void { _videoId = setValue };
public function set Path(setValue:String):void { _path = setValue };
public function set Id(setValue:int):void { _id = setValue };
public function PlayListItem(id:int, videoId:int, path:String)
{
_videoId = videoId;
_id = id;
_path = path;
}// end function
}
I think you were on the right track with your commented-out code. Be aware that the getOperation() will return an AbstractOperation, which in my mind is simply a pointer to the remote function. You can set arguments on the object, or simply pass the arguments when you call send(). I know some people have had issues with the argument property approach, so simply passing your arguments in the send function may be the smart way to go.
The following replace BuildServiceRequest and displayResult
private function BuildServiceRequest(evt:LoadEvent):void {
webService.removeEventListener(LoadEvent.LOAD, BuildServiceRequest);
serviceOperation.addEventListener(ResultEvent.RESULT, displayResult);
serviceOperation = webService.getOperation("GetPlaylist");
serviceOperation.send(394575);
}
private function displayResult(e:ResultEvent):void {
// Store the token as our array.
_playListItems = e.token;
var msg:String;
// Loop through the array
for each (var entry:Object in _playListItems) {
msg = "";
// For every key:value pair, compose a message to trace
for (var key:String in entry) {
msg += key + ":" + entry[key] + " ";
}
trace(msg);
}
}

How to create a list dynamically from a class name (which is passed as argument) and return the list in c#.net

How to create a list dynamically from a class name (which is passed as an argument) and return the list in C#.
Below code may not work. I have posted it to give an idea:
public T ConvertDataSetToList<T>(DataSet _ds, String tableName, string className)
{
Type classType=Type.GetType(className);
List<T> newList = new List<T>();
//System.Activator.CreateInstance(Type.GetType(className));
try
{
Details _Details;
for (int iRowCount = 0; iRowCount < _ds.Tables[tableName].Rows.Count; iRowCount++)
{
_Details = FillDTO(_ds.Tables[tableName].Rows[iRowCount]);
newList.Add(_msDetails);
}
}
catch (Exception ex) { }
return newList;
}
You can dot it with some basic mapping stuff.
//Maps a dataset
public List<T> MapDataSet<T>(DataSet anyDataset
, string tablename) where T : new()
{
return MapDataTable<T>(anyDataset.Tables[tablename]);
}
// Maps a datatable
public List<T> MapDataTable<T>(DataTable table) where T : new()
{
List<T> result = new List<T>();
foreach(DataRow row in table.Rows)
{
result.Add(MapDataRow<T>(row));
}
return result;
}
// maps a DataRow to an arbitrary class (rudimentary)
public T MapDataRow<T>(DataRow row) where T: new()
{
// we map columns to class properties
Type destinationType = typeof(T);
// create our new class
T mappedTo = new T();
// iterate over the columns
for(int columnIndex=0;columnIndex<row.ItemArray.Length;columnIndex++)
{
// get a matching property of our class
PropertyInfo fieldTo = destinationType.GetProperty(
row.Table.Columns[columnIndex].ColumnName );
if (fieldTo !=null)
{
// map our fieldvalue to our property
fieldTo.SetValue(mappedTo, row[columnIndex], new object[] {});
}
else
{
// sorry, field doens't match any property on class
}
}
return mappedTo;
}
Here is basic test app to demonstrate its usage
void Main()
{
DataTable dt = new DataTable("hello");
dt.Columns.Add("foo");
dt.Columns.Add("bar");
dt.Columns.Add("foobar");
DataRow row = dt.NewRow();
row[0]="blah1";
row[1] ="two";
row[2] = "fb1";
dt.Rows.Add(row);
row = dt.NewRow();
row[0]="apples";
row[1] ="pears";
row[2] = "duh";
dt.Rows.Add(row);
List<DTO> list = MapDataTable<DTO>(dt);
List<SecondDTO> list2 = MapDataTable<SecondDTO>(dt);
}
// sample DTO object
public class DTO
{
public string foo { get; set;}
public string bar { get; set; }
}
// another sample DTO object
public class SecondDTO
{
public string foo { get; set;}
public string foobar { get; set; }
}